blob: 174709bab27db5c30f17ff790dd9731a10c9f3fb [file] [log] [blame]
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +00001// Copyright 2015 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.skyframe;
15
16import static com.google.common.truth.Truth.assertThat;
17import static com.google.common.truth.Truth.assertWithMessage;
18import static com.google.devtools.build.lib.actions.FilesetTraversalParams.PackageBoundaryMode.CROSS;
19import static com.google.devtools.build.lib.actions.FilesetTraversalParams.PackageBoundaryMode.DONT_CROSS;
20import static com.google.devtools.build.lib.actions.FilesetTraversalParams.PackageBoundaryMode.REPORT_ERROR;
21
22import com.google.common.base.Function;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000023import com.google.common.collect.Collections2;
24import com.google.common.collect.ImmutableList;
25import com.google.common.collect.ImmutableMap;
26import com.google.common.collect.ImmutableSet;
27import com.google.devtools.build.lib.actions.Artifact;
28import com.google.devtools.build.lib.actions.FilesetOutputSymlink;
29import com.google.devtools.build.lib.actions.FilesetTraversalParams;
30import com.google.devtools.build.lib.actions.FilesetTraversalParams.PackageBoundaryMode;
31import com.google.devtools.build.lib.actions.FilesetTraversalParamsFactory;
32import com.google.devtools.build.lib.actions.Root;
33import com.google.devtools.build.lib.cmdline.Label;
34import com.google.devtools.build.lib.cmdline.PackageIdentifier;
35import com.google.devtools.build.lib.events.NullEventHandler;
36import com.google.devtools.build.lib.packages.FilesetEntry.SymlinkBehavior;
37import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
Florian Weikertcca703a2015-12-07 09:56:38 +000038import com.google.devtools.build.lib.testutil.FoundationTestCase;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000039import com.google.devtools.build.lib.util.BlazeClock;
40import com.google.devtools.build.lib.util.Fingerprint;
Mark Schaller6df81792015-12-10 18:47:47 +000041import com.google.devtools.build.lib.util.Preconditions;
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000042import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
43import com.google.devtools.build.lib.vfs.Path;
44import com.google.devtools.build.lib.vfs.PathFragment;
45import com.google.devtools.build.lib.vfs.RootedPath;
46import com.google.devtools.build.skyframe.EvaluationResult;
47import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator;
48import com.google.devtools.build.skyframe.MemoizingEvaluator;
49import com.google.devtools.build.skyframe.RecordingDifferencer;
50import com.google.devtools.build.skyframe.SequentialBuildDriver;
51import com.google.devtools.build.skyframe.SkyFunction;
52import com.google.devtools.build.skyframe.SkyFunctionName;
53import com.google.devtools.build.skyframe.SkyKey;
54import com.google.devtools.build.skyframe.SkyValue;
55
Florian Weikert92b22362015-12-03 10:17:18 +000056import org.junit.Before;
57import org.junit.Test;
58import org.junit.runner.RunWith;
59import org.junit.runners.JUnit4;
60
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000061import java.util.Arrays;
62import java.util.Collection;
63import java.util.HashMap;
64import java.util.List;
65import java.util.Map;
66import java.util.Set;
67import java.util.UUID;
68import java.util.concurrent.atomic.AtomicReference;
69
70import javax.annotation.Nullable;
71
72/** Tests for {@link FilesetEntryFunction}. */
Florian Weikert92b22362015-12-03 10:17:18 +000073@RunWith(JUnit4.class)
Florian Weikertcca703a2015-12-07 09:56:38 +000074public final class FilesetEntryFunctionTest extends FoundationTestCase {
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000075
76 private TimestampGranularityMonitor tsgm = new TimestampGranularityMonitor(BlazeClock.instance());
77 private MemoizingEvaluator evaluator;
78 private SequentialBuildDriver driver;
79 private RecordingDifferencer differencer;
80 private AtomicReference<PathPackageLocator> pkgLocator;
81
Florian Weikert92b22362015-12-03 10:17:18 +000082 @Before
83 public final void setUp() throws Exception {
Lukacs Berkid3262d12015-10-30 14:33:51 +000084 pkgLocator = new AtomicReference<>(
85 new PathPackageLocator(outputBase, ImmutableList.of(rootDirectory)));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000086 AtomicReference<ImmutableSet<PackageIdentifier>> deletedPackages =
87 new AtomicReference<>(ImmutableSet.<PackageIdentifier>of());
Kristina Chodorowf9fdc8d2015-12-08 12:49:31 +000088 ExternalFilesHelper externalFilesHelper = new ExternalFilesHelper(pkgLocator, false);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000089
90 Map<SkyFunctionName, SkyFunction> skyFunctions = new HashMap<>();
91
92 skyFunctions.put(SkyFunctions.FILE_STATE, new FileStateFunction(tsgm, externalFilesHelper));
Kristina Chodorowf9fdc8d2015-12-08 12:49:31 +000093 skyFunctions.put(SkyFunctions.FILE, new FileFunction(pkgLocator));
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +000094 skyFunctions.put(SkyFunctions.DIRECTORY_LISTING, new DirectoryListingFunction());
95 skyFunctions.put(
96 SkyFunctions.DIRECTORY_LISTING_STATE,
97 new DirectoryListingStateFunction(externalFilesHelper));
98 skyFunctions.put(
99 SkyFunctions.RECURSIVE_FILESYSTEM_TRAVERSAL, new RecursiveFilesystemTraversalFunction());
100 skyFunctions.put(SkyFunctions.PACKAGE_LOOKUP, new PackageLookupFunction(deletedPackages));
Eric Fellheimer7ef96d72015-11-12 02:28:44 +0000101 skyFunctions.put(SkyFunctions.BLACKLISTED_PACKAGE_PREFIXES,
102 new BlacklistedPackagePrefixesFunction());
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000103 skyFunctions.put(SkyFunctions.FILESET_ENTRY, new FilesetEntryFunction());
104
105 differencer = new RecordingDifferencer();
106 evaluator = new InMemoryMemoizingEvaluator(skyFunctions, differencer);
107 driver = new SequentialBuildDriver(evaluator);
108 PrecomputedValue.BUILD_ID.set(differencer, UUID.randomUUID());
109 PrecomputedValue.PATH_PACKAGE_LOCATOR.set(differencer, pkgLocator.get());
Eric Fellheimer7ef96d72015-11-12 02:28:44 +0000110 PrecomputedValue.BLACKLISTED_PACKAGE_PREFIXES_FILE.set(differencer,
111 PathFragment.EMPTY_FRAGMENT);
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000112 }
113
114 private Artifact getSourceArtifact(String path) throws Exception {
115 return new Artifact(new PathFragment(path), Root.asSourceRoot(rootDirectory));
116 }
117
118 private Artifact createSourceArtifact(String path) throws Exception {
119 Artifact result = getSourceArtifact(path);
120 createFile(result, "foo");
121 return result;
122 }
123
124 private static RootedPath rootedPath(Artifact artifact) {
125 return RootedPath.toRootedPath(artifact.getRoot().getPath(), artifact.getRootRelativePath());
126 }
127
128 private static RootedPath childOf(Artifact artifact, String relative) {
129 return RootedPath.toRootedPath(
130 artifact.getRoot().getPath(), artifact.getRootRelativePath().getRelative(relative));
131 }
132
133 private static RootedPath siblingOf(Artifact artifact, String relative) {
134 PathFragment parent =
135 Preconditions.checkNotNull(artifact.getRootRelativePath().getParentDirectory());
136 return RootedPath.toRootedPath(artifact.getRoot().getPath(), parent.getRelative(relative));
137 }
138
139 private void createFile(Path path, String... contents) throws Exception {
140 if (!path.getParentDirectory().exists()) {
141 scratch.dir(path.getParentDirectory().getPathString());
142 }
143 scratch.file(path.getPathString(), contents);
144 }
145
146 private void createFile(Artifact artifact, String... contents) throws Exception {
147 createFile(artifact.getPath(), contents);
148 }
149
150 private RootedPath createFile(RootedPath path, String... contents) throws Exception {
151 createFile(path.asPath(), contents);
152 return path;
153 }
154
155 private <T extends SkyValue> EvaluationResult<T> eval(SkyKey key) throws Exception {
156 return driver.evaluate(
157 ImmutableList.of(key),
158 false,
159 SkyframeExecutor.DEFAULT_THREAD_COUNT,
160 NullEventHandler.INSTANCE);
161 }
162
163 private FilesetEntryValue evalFilesetTraversal(FilesetTraversalParams params) throws Exception {
164 SkyKey key = FilesetEntryValue.key(params);
165 EvaluationResult<FilesetEntryValue> result = eval(key);
166 assertThat(result.hasError()).isFalse();
167 return result.get(key);
168 }
169
170 private static FilesetOutputSymlink symlink(String from, Artifact to) {
171 return new FilesetOutputSymlink(new PathFragment(from), to.getPath().asFragment());
172 }
173
174 private static FilesetOutputSymlink symlink(String from, String to) {
175 return new FilesetOutputSymlink(new PathFragment(from), new PathFragment(to));
176 }
177
178 private static FilesetOutputSymlink symlink(String from, RootedPath to) {
179 return new FilesetOutputSymlink(new PathFragment(from), to.asPath().asFragment());
180 }
181
182 private void assertSymlinksInOrder(
183 FilesetTraversalParams request, FilesetOutputSymlink... expectedSymlinks) throws Exception {
184 List<FilesetOutputSymlink> expected = Arrays.asList(expectedSymlinks);
185 Collection<FilesetOutputSymlink> actual =
186 Collections2.transform(
187 evalFilesetTraversal(request).getSymlinks(),
188 // Strip the metadata from the actual results.
189 new Function<FilesetOutputSymlink, FilesetOutputSymlink>() {
190 @Override
191 public FilesetOutputSymlink apply(FilesetOutputSymlink input) {
192 return new FilesetOutputSymlink(input.name, input.target);
193 }
194 });
195 assertThat(actual).containsExactlyElementsIn(expected).inOrder();
196 }
197
198 private static Label label(String label) throws Exception {
199 return Label.parseAbsolute(label);
200 }
201
Florian Weikert92b22362015-12-03 10:17:18 +0000202 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000203 public void testFileTraversalForFile() throws Exception {
204 Artifact file = createSourceArtifact("foo/file.real");
205 FilesetTraversalParams params =
206 FilesetTraversalParamsFactory.fileTraversal(
207 /*ownerLabel=*/ label("//foo"),
208 /*fileToTraverse=*/ file,
209 /*destPath=*/ new PathFragment("output-name"),
210 /*symlinkBehaviorMode=*/ SymlinkBehavior.COPY,
211 /*pkgBoundaryMode=*/ DONT_CROSS);
212 assertSymlinksInOrder(params, symlink("output-name", file));
213 }
214
215 private void assertFileTraversalForFileSymlink(SymlinkBehavior symlinks) throws Exception {
216 Artifact file = createSourceArtifact("foo/file.real");
217 Artifact symlink = getSourceArtifact("foo/file.sym");
218 symlink.getPath().createSymbolicLink(new PathFragment("file.real"));
219
220 FilesetTraversalParams params =
221 FilesetTraversalParamsFactory.fileTraversal(
222 /*ownerLabel=*/ label("//foo"),
223 /*fileToTraverse=*/ symlink,
224 /*destPath=*/ new PathFragment("output-name"),
225 /*symlinkBehaviorMode=*/ symlinks,
226 /*pkgBoundaryMode=*/ DONT_CROSS);
227 switch (symlinks) {
228 case COPY:
229 assertSymlinksInOrder(params, symlink("output-name", "file.real"));
230 break;
231 case DEREFERENCE:
232 assertSymlinksInOrder(params, symlink("output-name", file));
233 break;
234 default:
235 throw new IllegalStateException(symlinks.toString());
236 }
237 }
238
Florian Weikert92b22362015-12-03 10:17:18 +0000239 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000240 public void testFileTraversalForFileSymlinkNoFollow() throws Exception {
241 assertFileTraversalForFileSymlink(SymlinkBehavior.COPY);
242 }
243
Florian Weikert92b22362015-12-03 10:17:18 +0000244 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000245 public void testFileTraversalForFileSymlinkFollow() throws Exception {
246 assertFileTraversalForFileSymlink(SymlinkBehavior.DEREFERENCE);
247 }
248
Florian Weikert92b22362015-12-03 10:17:18 +0000249 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000250 public void testFileTraversalForDirectory() throws Exception {
251 Artifact dir = getSourceArtifact("foo/dir_real");
252 RootedPath fileA = createFile(childOf(dir, "file.a"), "hello");
253 RootedPath fileB = createFile(childOf(dir, "sub/file.b"), "world");
254
255 FilesetTraversalParams params =
256 FilesetTraversalParamsFactory.fileTraversal(
257 /*ownerLabel=*/ label("//foo"),
258 /*fileToTraverse=*/ dir,
259 /*destPath=*/ new PathFragment("output-name"),
260 /*symlinkBehaviorMode=*/ SymlinkBehavior.COPY,
261 /*pkgBoundaryMode=*/ DONT_CROSS);
262 assertSymlinksInOrder(
263 params, symlink("output-name/file.a", fileA), symlink("output-name/sub/file.b", fileB));
264 }
265
266 private void assertFileTraversalForDirectorySymlink(SymlinkBehavior symlinks) throws Exception {
267 Artifact dir = getSourceArtifact("foo/dir_real");
268 Artifact symlink = getSourceArtifact("foo/dir_sym");
269 createFile(childOf(dir, "file.a"), "hello");
270 createFile(childOf(dir, "sub/file.b"), "world");
271 symlink.getPath().createSymbolicLink(new PathFragment("dir_real"));
272
273 FilesetTraversalParams params =
274 FilesetTraversalParamsFactory.fileTraversal(
275 /*ownerLabel=*/ label("//foo"),
276 /*fileToTraverse=*/ symlink,
277 /*destPath=*/ new PathFragment("output-name"),
278 /*symlinkBehaviorMode=*/ symlinks,
279 /*pkgBoundaryMode=*/ DONT_CROSS);
280 switch (symlinks) {
281 case COPY:
282 assertSymlinksInOrder(params, symlink("output-name", "dir_real"));
283 break;
284 case DEREFERENCE:
285 assertSymlinksInOrder(params, symlink("output-name", dir));
286 break;
287 default:
288 throw new IllegalStateException(symlinks.toString());
289 }
290 }
291
Florian Weikert92b22362015-12-03 10:17:18 +0000292 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000293 public void testFileTraversalForDirectorySymlinkFollow() throws Exception {
294 assertFileTraversalForDirectorySymlink(SymlinkBehavior.COPY);
295 }
296
Florian Weikert92b22362015-12-03 10:17:18 +0000297 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000298 public void testFileTraversalForDirectorySymlinkNoFollow() throws Exception {
299 assertFileTraversalForDirectorySymlink(SymlinkBehavior.DEREFERENCE);
300 }
301
302 private void assertRecursiveTraversalForDirectory(
303 SymlinkBehavior symlinks, PackageBoundaryMode pkgBoundaryMode) throws Exception {
304 Artifact dir = getSourceArtifact("foo/dir");
305 RootedPath fileA = createFile(childOf(dir, "file.a"), "blah");
306 RootedPath fileAsym = childOf(dir, "subdir/file.a.sym");
307 RootedPath buildFile = createFile(childOf(dir, "subpkg/BUILD"), "blah");
308 RootedPath fileB = createFile(childOf(dir, "subpkg/file.b"), "blah");
309 fileAsym.asPath().getParentDirectory().createDirectory();
310 fileAsym.asPath().createSymbolicLink(new PathFragment("../file.a"));
311
312 FilesetOutputSymlink outA = symlink("output-name/file.a", childOf(dir, "file.a"));
313 FilesetOutputSymlink outAsym = null;
314 FilesetOutputSymlink outBuild = symlink("output-name/subpkg/BUILD", buildFile);
315 FilesetOutputSymlink outB = symlink("output-name/subpkg/file.b", fileB);
316 switch (symlinks) {
317 case COPY:
318 outAsym = symlink("output-name/subdir/file.a.sym", "../file.a");
319 break;
320 case DEREFERENCE:
321 outAsym = symlink("output-name/subdir/file.a.sym", fileA);
322 break;
323 default:
324 throw new IllegalStateException(symlinks.toString());
325 }
326
327 FilesetTraversalParams params =
328 FilesetTraversalParamsFactory.recursiveTraversalOfDirectory(
329 /*ownerLabel=*/ label("//foo"),
330 /*directoryToTraverse=*/ dir,
331 /*destPath=*/ new PathFragment("output-name"),
332 /*excludes=*/ null,
333 /*symlinkBehaviorMode=*/ symlinks,
334 /*pkgBoundaryMode=*/ pkgBoundaryMode);
335 switch (pkgBoundaryMode) {
336 case CROSS:
337 assertSymlinksInOrder(params, outA, outAsym, outBuild, outB);
338 break;
339 case DONT_CROSS:
340 assertSymlinksInOrder(params, outA, outAsym);
341 break;
342 case REPORT_ERROR:
343 SkyKey key = FilesetEntryValue.key(params);
344 EvaluationResult<SkyValue> result = eval(key);
345 assertThat(result.hasError()).isTrue();
346 assertThat(result.getError(key).getException().getMessage())
347 .contains("'foo/dir' crosses package boundary into package rooted at foo/dir/subpkg");
348 break;
349 default:
350 throw new IllegalStateException(pkgBoundaryMode.toString());
351 }
352 }
353
Florian Weikert92b22362015-12-03 10:17:18 +0000354 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000355 public void testRecursiveTraversalForDirectoryCrossNoFollow() throws Exception {
356 assertRecursiveTraversalForDirectory(SymlinkBehavior.COPY, CROSS);
357 }
358
Florian Weikert92b22362015-12-03 10:17:18 +0000359 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000360 public void testRecursiveTraversalForDirectoryDontCrossNoFollow() throws Exception {
361 assertRecursiveTraversalForDirectory(SymlinkBehavior.COPY, DONT_CROSS);
362 }
363
Florian Weikert92b22362015-12-03 10:17:18 +0000364 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000365 public void testRecursiveTraversalForDirectoryReportErrorNoFollow() throws Exception {
366 assertRecursiveTraversalForDirectory(SymlinkBehavior.COPY, REPORT_ERROR);
367 }
368
Florian Weikert92b22362015-12-03 10:17:18 +0000369 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000370 public void testRecursiveTraversalForDirectoryCrossFollow() throws Exception {
371 assertRecursiveTraversalForDirectory(SymlinkBehavior.DEREFERENCE, CROSS);
372 }
373
Florian Weikert92b22362015-12-03 10:17:18 +0000374 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000375 public void testRecursiveTraversalForDirectoryDontCrossFollow() throws Exception {
376 assertRecursiveTraversalForDirectory(SymlinkBehavior.DEREFERENCE, DONT_CROSS);
377 }
378
Florian Weikert92b22362015-12-03 10:17:18 +0000379 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000380 public void testRecursiveTraversalForDirectoryReportErrorFollow() throws Exception {
381 assertRecursiveTraversalForDirectory(SymlinkBehavior.DEREFERENCE, REPORT_ERROR);
382 }
383
384 private void assertRecursiveTraversalForDirectorySymlink(
385 SymlinkBehavior symlinks, PackageBoundaryMode pkgBoundaryMode) throws Exception {
386 Artifact dir = getSourceArtifact("foo/dir_real");
387 Artifact symlink = getSourceArtifact("foo/dir_sym");
388 createFile(childOf(dir, "file.a"), "blah");
389 RootedPath fileAsym = childOf(dir, "subdir/file.a.sym");
390 createFile(childOf(dir, "subpkg/BUILD"), "blah");
391 createFile(childOf(dir, "subpkg/file.b"), "blah");
392 fileAsym.asPath().getParentDirectory().createDirectory();
393 fileAsym.asPath().createSymbolicLink(new PathFragment("../file.a"));
394 symlink.getPath().createSymbolicLink(new PathFragment("dir_real"));
395
396 FilesetOutputSymlink outA = symlink("output-name/file.a", childOf(symlink, "file.a"));
397 FilesetOutputSymlink outASym = null;
398 FilesetOutputSymlink outBuild =
399 symlink("output-name/subpkg/BUILD", childOf(symlink, "subpkg/BUILD"));
400 FilesetOutputSymlink outB =
401 symlink("output-name/subpkg/file.b", childOf(symlink, "subpkg/file.b"));
402 switch (symlinks) {
403 case COPY:
404 outASym = symlink("output-name/subdir/file.a.sym", "../file.a");
405 break;
406 case DEREFERENCE:
407 outASym = symlink("output-name/subdir/file.a.sym", childOf(dir, "file.a"));
408 break;
409 default:
410 throw new IllegalStateException(symlinks.toString());
411 }
412
413 FilesetTraversalParams params =
414 FilesetTraversalParamsFactory.recursiveTraversalOfDirectory(
415 /*ownerLabel=*/ label("//foo"),
416 /*directoryToTraverse=*/ symlink,
417 /*destPath=*/ new PathFragment("output-name"),
418 /*excludes=*/ null,
419 /*symlinkBehaviorMode=*/ symlinks,
420 /*pkgBoundaryMode=*/ pkgBoundaryMode);
421 switch (pkgBoundaryMode) {
422 case CROSS:
423 assertSymlinksInOrder(params, outA, outASym, outBuild, outB);
424 break;
425 case DONT_CROSS:
426 assertSymlinksInOrder(params, outA, outASym);
427 break;
428 case REPORT_ERROR:
429 SkyKey key = FilesetEntryValue.key(params);
430 EvaluationResult<SkyValue> result = eval(key);
431 assertThat(result.hasError()).isTrue();
432 assertThat(result.getError(key).getException().getMessage())
433 .contains(
434 "'foo/dir_sym' crosses package boundary into package rooted at foo/dir_sym/subpkg");
435 break;
436 default:
437 throw new IllegalStateException(pkgBoundaryMode.toString());
438 }
439 }
440
Florian Weikert92b22362015-12-03 10:17:18 +0000441 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000442 public void testRecursiveTraversalForDirectorySymlinkNoFollowCross() throws Exception {
443 assertRecursiveTraversalForDirectorySymlink(SymlinkBehavior.COPY, CROSS);
444 }
445
Florian Weikert92b22362015-12-03 10:17:18 +0000446 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000447 public void testRecursiveTraversalForDirectorySymlinkNoFollowDontCross() throws Exception {
448 assertRecursiveTraversalForDirectorySymlink(SymlinkBehavior.COPY, DONT_CROSS);
449 }
450
Florian Weikert92b22362015-12-03 10:17:18 +0000451 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000452 public void testRecursiveTraversalForDirectorySymlinkNoFollowReportError() throws Exception {
453 assertRecursiveTraversalForDirectorySymlink(SymlinkBehavior.COPY, REPORT_ERROR);
454 }
455
Florian Weikert92b22362015-12-03 10:17:18 +0000456 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000457 public void testRecursiveTraversalForDirectorySymlinkFollowCross() throws Exception {
458 assertRecursiveTraversalForDirectorySymlink(SymlinkBehavior.DEREFERENCE, CROSS);
459 }
460
Florian Weikert92b22362015-12-03 10:17:18 +0000461 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000462 public void testRecursiveTraversalForDirectorySymlinkFollowDontCross() throws Exception {
463 assertRecursiveTraversalForDirectorySymlink(SymlinkBehavior.DEREFERENCE, DONT_CROSS);
464 }
465
Florian Weikert92b22362015-12-03 10:17:18 +0000466 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000467 public void testRecursiveTraversalForDirectorySymlinkFollowReportError() throws Exception {
468 assertRecursiveTraversalForDirectorySymlink(SymlinkBehavior.DEREFERENCE, REPORT_ERROR);
469 }
470
471 private void assertRecursiveTraversalForPackage(
472 SymlinkBehavior symlinks, PackageBoundaryMode pkgBoundaryMode) throws Exception {
473 Artifact buildFile = createSourceArtifact("foo/BUILD");
474 Artifact subpkgBuildFile = createSourceArtifact("foo/subpkg/BUILD");
475 Artifact subpkgSymlink = getSourceArtifact("foo/subpkg_sym");
476
477 RootedPath fileA = createFile(siblingOf(buildFile, "file.a"), "blah");
478 RootedPath fileAsym = siblingOf(buildFile, "subdir/file.a.sym");
479 RootedPath fileB = createFile(siblingOf(subpkgBuildFile, "file.b"), "blah");
480
481 scratch.dir(fileAsym.asPath().getParentDirectory().getPathString());
482 fileAsym.asPath().createSymbolicLink(new PathFragment("../file.a"));
483 subpkgSymlink.getPath().createSymbolicLink(new PathFragment("subpkg"));
484
485 FilesetOutputSymlink outBuild = symlink("output-name/BUILD", buildFile);
486 FilesetOutputSymlink outA = symlink("output-name/file.a", fileA);
487 FilesetOutputSymlink outAsym = null;
488 FilesetOutputSymlink outSubpkgBuild = symlink("output-name/subpkg/BUILD", subpkgBuildFile);
489 FilesetOutputSymlink outSubpkgB = symlink("output-name/subpkg/file.b", fileB);
490 FilesetOutputSymlink outSubpkgSymBuild;
491 switch (symlinks) {
492 case COPY:
493 outAsym = symlink("output-name/subdir/file.a.sym", "../file.a");
494 outSubpkgSymBuild = symlink("output-name/subpkg_sym", "subpkg");
495 break;
496 case DEREFERENCE:
497 outAsym = symlink("output-name/subdir/file.a.sym", fileA);
498 outSubpkgSymBuild = symlink("output-name/subpkg_sym", getSourceArtifact("foo/subpkg"));
499 break;
500 default:
501 throw new IllegalStateException(symlinks.toString());
502 }
503
504 FilesetTraversalParams params =
505 FilesetTraversalParamsFactory.recursiveTraversalOfPackage(
506 /*ownerLabel=*/ label("//foo"),
507 /*directoryToTraverse=*/ buildFile,
508 /*destPath=*/ new PathFragment("output-name"),
509 /*excludes=*/ null,
510 /*symlinkBehaviorMode=*/ symlinks,
511 /*pkgBoundaryMode=*/ pkgBoundaryMode);
512 switch (pkgBoundaryMode) {
513 case CROSS:
514 assertSymlinksInOrder(
515 params, outBuild, outA, outSubpkgSymBuild, outAsym, outSubpkgBuild, outSubpkgB);
516 break;
517 case DONT_CROSS:
518 assertSymlinksInOrder(params, outBuild, outA, outAsym);
519 break;
520 case REPORT_ERROR:
521 SkyKey key = FilesetEntryValue.key(params);
522 EvaluationResult<SkyValue> result = eval(key);
523 assertThat(result.hasError()).isTrue();
524 assertThat(result.getError(key).getException().getMessage())
525 .contains("'foo' crosses package boundary into package rooted at foo/subpkg");
526 break;
527 default:
528 throw new IllegalStateException(pkgBoundaryMode.toString());
529 }
530 }
531
Florian Weikert92b22362015-12-03 10:17:18 +0000532 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000533 public void testRecursiveTraversalForPackageNoFollowCross() throws Exception {
534 assertRecursiveTraversalForPackage(SymlinkBehavior.COPY, CROSS);
535 }
536
Florian Weikert92b22362015-12-03 10:17:18 +0000537 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000538 public void testRecursiveTraversalForPackageNoFollowDontCross() throws Exception {
539 assertRecursiveTraversalForPackage(SymlinkBehavior.COPY, DONT_CROSS);
540 }
541
Florian Weikert92b22362015-12-03 10:17:18 +0000542 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000543 public void testRecursiveTraversalForPackageNoFollowReportError() throws Exception {
544 assertRecursiveTraversalForPackage(SymlinkBehavior.COPY, REPORT_ERROR);
545 }
546
Florian Weikert92b22362015-12-03 10:17:18 +0000547 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000548 public void testRecursiveTraversalForPackageFollowCross() throws Exception {
549 assertRecursiveTraversalForPackage(SymlinkBehavior.DEREFERENCE, CROSS);
550 }
551
Florian Weikert92b22362015-12-03 10:17:18 +0000552 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000553 public void testRecursiveTraversalForPackageFollowDontCross() throws Exception {
554 assertRecursiveTraversalForPackage(SymlinkBehavior.DEREFERENCE, DONT_CROSS);
555 }
556
Florian Weikert92b22362015-12-03 10:17:18 +0000557 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000558 public void testRecursiveTraversalForPackageFollowReportError() throws Exception {
559 assertRecursiveTraversalForPackage(SymlinkBehavior.DEREFERENCE, REPORT_ERROR);
560 }
561
Florian Weikert92b22362015-12-03 10:17:18 +0000562 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000563 public void testNestedFileFilesetTraversal() throws Exception {
564 Artifact path = getSourceArtifact("foo/bar.file");
565 createFile(path, "blah");
566 FilesetTraversalParams inner =
567 FilesetTraversalParamsFactory.fileTraversal(
568 /*ownerLabel=*/ label("//foo"),
569 /*fileToTraverse=*/ path,
570 /*destPath=*/ new PathFragment("inner-out"),
571 /*symlinkBehaviorMode=*/ SymlinkBehavior.COPY,
572 /*pkgBoundaryMode=*/ DONT_CROSS);
573 FilesetTraversalParams outer =
574 FilesetTraversalParamsFactory.nestedTraversal(
575 /*ownerLabel=*/ label("//foo:bar"),
576 /*nested=*/ inner,
577 /*destDir=*/ new PathFragment("outer-out"),
578 /*excludes=*/ null);
579 assertSymlinksInOrder(outer, symlink("outer-out/inner-out", rootedPath(path)));
580 }
581
582 private void assertNestedRecursiveFilesetTraversal(boolean useInnerDir) throws Exception {
583 Artifact dir = getSourceArtifact("foo/dir");
584 RootedPath fileA = createFile(childOf(dir, "file.a"), "hello");
585 RootedPath fileB = createFile(childOf(dir, "file.b"), "hello");
586 RootedPath fileC = createFile(childOf(dir, "sub/file.c"), "world");
587
588 FilesetTraversalParams inner =
589 FilesetTraversalParamsFactory.recursiveTraversalOfDirectory(
590 /*ownerLabel=*/ label("//foo"),
591 /*directoryToTraverse=*/ dir,
592 /*destPath=*/ new PathFragment(useInnerDir ? "inner-dir" : ""),
593 /*excludes=*/ null,
594 /*symlinkBehaviorMode=*/ SymlinkBehavior.COPY,
595 /*pkgBoundaryMode=*/ DONT_CROSS);
596 FilesetTraversalParams outer =
597 FilesetTraversalParamsFactory.nestedTraversal(
598 /*ownerLabel=*/ label("//foo"),
599 /*nested=*/ inner,
600 /*destDir=*/ new PathFragment("outer-dir"),
601 ImmutableSet.<String>of("file.a", "sub/file.c"));
602
603 if (useInnerDir) {
604 assertSymlinksInOrder(
605 outer,
606 // no file is excluded, since no files from "inner" are top-level in the outer Fileset
607 symlink("outer-dir/inner-dir/file.a", fileA),
608 symlink("outer-dir/inner-dir/file.b", fileB),
609 symlink("outer-dir/inner-dir/sub/file.c", fileC)); // only top-level files are excluded
610 } else {
611 assertSymlinksInOrder(
612 outer,
613 // file.a can be excluded because it's top-level (there's no output directory for "inner")
614 symlink("outer-dir/file.b", fileB),
615 symlink("outer-dir/sub/file.c", fileC)); // only top-level files could be excluded
616 }
617 }
618
Florian Weikert92b22362015-12-03 10:17:18 +0000619 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000620 public void testNestedRecursiveFilesetTraversalWithInnerDestDir() throws Exception {
621 assertNestedRecursiveFilesetTraversal(true);
622 }
623
Florian Weikert92b22362015-12-03 10:17:18 +0000624 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000625 public void testNestedRecursiveFilesetTraversalWithoutInnerDestDir() throws Exception {
626 assertNestedRecursiveFilesetTraversal(false);
627 }
628
Florian Weikert92b22362015-12-03 10:17:18 +0000629 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000630 public void testFileTraversalForDanglingSymlink() throws Exception {
631 Artifact linkName = getSourceArtifact("foo/dangling.sym");
632 RootedPath linkTarget = createFile(siblingOf(linkName, "target.file"), "blah");
633 linkName.getPath().createSymbolicLink(new PathFragment("target.file"));
634 linkTarget.asPath().delete();
635
636 FilesetTraversalParams params =
637 FilesetTraversalParamsFactory.fileTraversal(
638 /*ownerLabel=*/ label("//foo"),
639 /*fileToTraverse=*/ linkName,
640 /*destPath=*/ new PathFragment("output-name"),
641 /*symlinkBehaviorMode=*/ SymlinkBehavior.COPY,
642 /*pkgBoundaryMode=*/ DONT_CROSS);
643 assertSymlinksInOrder(params); // expect empty results
644 }
645
Laszlo Csomor0ad729f2015-12-02 15:20:35 +0000646 private void assertExclusionOfDanglingSymlink(SymlinkBehavior symlinkBehavior) throws Exception {
Laszlo Csomor0ad729f2015-12-02 15:20:35 +0000647 Artifact buildFile = getSourceArtifact("foo/BUILD");
Laszlo Csomor0ad729f2015-12-02 15:20:35 +0000648 createFile(buildFile);
Laszlo Csomor0ad729f2015-12-02 15:20:35 +0000649
Laszlo Csomor84fb4612015-12-03 12:47:25 +0000650 Artifact linkName = getSourceArtifact("foo/file.sym");
651 Artifact linkTarget = getSourceArtifact("foo/file.actual");
652 createFile(linkTarget);
653 linkName.getPath().createSymbolicLink(new PathFragment("file.actual"));
654
655 // Ensure the symlink and its target would be included if they weren't explicitly excluded.
656 FilesetTraversalParams params =
Laszlo Csomor0ad729f2015-12-02 15:20:35 +0000657 FilesetTraversalParamsFactory.recursiveTraversalOfPackage(
658 /* ownerLabel */ label("//foo"),
659 /* buildFile */ buildFile,
660 /* destPath */ new PathFragment("output-name"),
Laszlo Csomor84fb4612015-12-03 12:47:25 +0000661 /* excludes */ ImmutableSet.<String>of(),
Laszlo Csomor0ad729f2015-12-02 15:20:35 +0000662 /* symlinkBehaviorMode */ symlinkBehavior,
663 /* pkgBoundaryMode */ PackageBoundaryMode.DONT_CROSS);
Laszlo Csomor84fb4612015-12-03 12:47:25 +0000664 assertSymlinksInOrder(
665 params,
666 symlink("output-name/BUILD", buildFile),
667 symlink("output-name/file.actual", linkTarget),
668 symlinkBehavior == SymlinkBehavior.COPY
669 ? symlink("output-name/file.sym", "file.actual")
670 : symlink("output-name/file.sym", linkTarget));
671
672 // Delete the symlink's target to make it dangling.
673 // Exclude the symlink and make sure it's not included.
674 linkTarget.getPath().delete();
675 differencer.invalidate(ImmutableList.of(FileStateValue.key(rootedPath(linkTarget))));
676 params =
677 FilesetTraversalParamsFactory.recursiveTraversalOfPackage(
678 /* ownerLabel */ label("//foo"),
679 /* buildFile */ buildFile,
680 /* destPath */ new PathFragment("output-name"),
681 /* excludes */ ImmutableSet.of("file.sym"),
682 /* symlinkBehaviorMode */ symlinkBehavior,
683 /* pkgBoundaryMode */ PackageBoundaryMode.DONT_CROSS);
684 assertSymlinksInOrder(params, symlink("output-name/BUILD", buildFile));
Laszlo Csomor0ad729f2015-12-02 15:20:35 +0000685 }
686
Florian Weikert92b22362015-12-03 10:17:18 +0000687 @Test
Laszlo Csomor0ad729f2015-12-02 15:20:35 +0000688 public void testExclusionOfDanglingSymlinkWithSymlinkModeCopy() throws Exception {
689 assertExclusionOfDanglingSymlink(SymlinkBehavior.COPY);
690 }
691
Florian Weikert92b22362015-12-03 10:17:18 +0000692 @Test
Laszlo Csomor0ad729f2015-12-02 15:20:35 +0000693 public void testExclusionOfDanglingSymlinkWithSymlinkModeDereference() throws Exception {
694 assertExclusionOfDanglingSymlink(SymlinkBehavior.DEREFERENCE);
695 }
696
Florian Weikert92b22362015-12-03 10:17:18 +0000697 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000698 public void testFileTraversalForNonExistentFile() throws Exception {
699 Artifact path = getSourceArtifact("foo/non-existent");
700 FilesetTraversalParams params =
701 FilesetTraversalParamsFactory.fileTraversal(
702 /*ownerLabel=*/ label("//foo"),
703 /*fileToTraverse=*/ path,
704 /*destPath=*/ new PathFragment("output-name"),
705 /*symlinkBehaviorMode=*/ SymlinkBehavior.COPY,
706 /*pkgBoundaryMode=*/ DONT_CROSS);
707 assertSymlinksInOrder(params); // expect empty results
708 }
709
Florian Weikert92b22362015-12-03 10:17:18 +0000710 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000711 public void testRecursiveTraversalForDanglingSymlink() throws Exception {
712 Artifact linkName = getSourceArtifact("foo/dangling.sym");
713 RootedPath linkTarget = createFile(siblingOf(linkName, "target.file"), "blah");
714 linkName.getPath().createSymbolicLink(new PathFragment("target.file"));
715 linkTarget.asPath().delete();
716
717 FilesetTraversalParams params =
718 FilesetTraversalParamsFactory.recursiveTraversalOfDirectory(
719 /*ownerLabel=*/ label("//foo"),
720 /*directoryToTraverse=*/ linkName,
721 /*destPath=*/ new PathFragment("output-name"),
722 /*excludes=*/ null,
723 /*symlinkBehaviorMode=*/ SymlinkBehavior.COPY,
724 /*pkgBoundaryMode=*/ DONT_CROSS);
725 assertSymlinksInOrder(params); // expect empty results
726 }
727
Florian Weikert92b22362015-12-03 10:17:18 +0000728 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000729 public void testRecursiveTraversalForNonExistentFile() throws Exception {
730 Artifact path = getSourceArtifact("foo/non-existent");
731
732 FilesetTraversalParams params =
733 FilesetTraversalParamsFactory.recursiveTraversalOfDirectory(
734 /*ownerLabel=*/ label("//foo"),
735 /*directoryToTraverse=*/ path,
736 /*destPath=*/ new PathFragment("output-name"),
737 /*excludes=*/ null,
738 /*symlinkBehaviorMode=*/ SymlinkBehavior.COPY,
739 /*pkgBoundaryMode=*/ DONT_CROSS);
740 assertSymlinksInOrder(params); // expect empty results
741 }
742
743 /**
744 * Tests that the fingerprint is a function of all arguments of the factory method.
745 *
746 * <p>Implementations must provide:
747 * <ul>
748 * <li>two different values (a domain) for each argument of the factory method and whether or not
749 * it is expected to influence the fingerprint
750 * <li>a way to instantiate {@link FilesetTraversalParams} with a given set of arguments from the
751 * specified domains
752 * </ul>
753 *
754 * <p>The tests will instantiate pairs of {@link FilesetTraversalParams} objects with only a given
755 * attribute differing, and observe whether the fingerprints differ (if they are expected to) or
756 * are the same (otherwise).
757 */
758 private abstract static class FingerprintTester {
759 private final Map<String, Domain> domains;
760
761 FingerprintTester(Map<String, Domain> domains) {
762 this.domains = domains;
763 }
764
765 abstract FilesetTraversalParams create(Map<String, ?> kwArgs) throws Exception;
766
767 private Map<String, ?> getDefaultArgs() {
768 return getKwArgs(null);
769 }
770
771 private Map<String, ?> getKwArgs(@Nullable String useAlternateFor) {
772 Map<String, Object> values = new HashMap<>();
773 for (Map.Entry<String, Domain> d : domains.entrySet()) {
774 values.put(
775 d.getKey(),
776 d.getKey().equals(useAlternateFor) ? d.getValue().valueA : d.getValue().valueB);
777 }
778 return values;
779 }
780
781 public void doTest() throws Exception {
782 Fingerprint fp = new Fingerprint();
783
784 create(getDefaultArgs()).fingerprint(fp);
785 String primary = fp.hexDigestAndReset();
786
787 for (String argName : domains.keySet()) {
788 create(getKwArgs(argName)).fingerprint(fp);
789 String secondary = fp.hexDigestAndReset();
790
791 if (domains.get(argName).includedInFingerprint) {
792 assertWithMessage(
793 "Argument '"
794 + argName
795 + "' was expected to be included in the"
796 + " fingerprint, but wasn't")
797 .that(primary)
798 .isNotEqualTo(secondary);
799 } else {
800 assertWithMessage(
801 "Argument '"
802 + argName
803 + "' was expected not to be included in the"
804 + " fingerprint, but was")
805 .that(primary)
806 .isEqualTo(secondary);
807 }
808 }
809 }
810 }
811
812 private static final class Domain {
813 boolean includedInFingerprint;
814 Object valueA;
815 Object valueB;
816
817 Domain(boolean includedInFingerprint, Object valueA, Object valueB) {
818 this.includedInFingerprint = includedInFingerprint;
819 this.valueA = valueA;
820 this.valueB = valueB;
821 }
822 }
823
824 private static Domain partOfFingerprint(Object valueA, Object valueB) {
825 return new Domain(true, valueA, valueB);
826 }
827
828 private static Domain notPartOfFingerprint(Object valueA, Object valueB) {
829 return new Domain(false, valueA, valueB);
830 }
831
Florian Weikert92b22362015-12-03 10:17:18 +0000832 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000833 public void testFingerprintOfFileTraversal() throws Exception {
834 new FingerprintTester(
835 ImmutableMap.<String, Domain>of(
836 "ownerLabel", notPartOfFingerprint("//foo", "//bar"),
837 "fileToTraverse", partOfFingerprint("foo/file.a", "bar/file.b"),
838 "destPath", partOfFingerprint("out1", "out2"),
839 "symlinkBehaviorMode",
840 partOfFingerprint(SymlinkBehavior.COPY, SymlinkBehavior.DEREFERENCE),
841 "pkgBoundaryMode", partOfFingerprint(CROSS, DONT_CROSS))) {
842 @Override
843 FilesetTraversalParams create(Map<String, ?> kwArgs) throws Exception {
844 return FilesetTraversalParamsFactory.fileTraversal(
845 label((String) kwArgs.get("ownerLabel")),
846 getSourceArtifact((String) kwArgs.get("fileToTraverse")),
847 new PathFragment((String) kwArgs.get("destPath")),
848 ((SymlinkBehavior) kwArgs.get("symlinkBehaviorMode")),
849 (PackageBoundaryMode) kwArgs.get("pkgBoundaryMode"));
850 }
851 }.doTest();
852 }
853
Florian Weikert92b22362015-12-03 10:17:18 +0000854 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000855 public void testFingerprintOfDirectoryTraversal() throws Exception {
856 new FingerprintTester(
857 ImmutableMap.<String, Domain>builder()
858 .put("ownerLabel", notPartOfFingerprint("//foo", "//bar"))
859 .put("directoryToTraverse", partOfFingerprint("foo/dir_a", "bar/dir_b"))
860 .put("destPath", partOfFingerprint("out1", "out2"))
861 .put(
862 "excludes",
863 partOfFingerprint(ImmutableSet.<String>of(), ImmutableSet.<String>of("blah")))
864 .put(
865 "symlinkBehaviorMode",
866 partOfFingerprint(SymlinkBehavior.COPY, SymlinkBehavior.DEREFERENCE))
867 .put("pkgBoundaryMode", partOfFingerprint(CROSS, DONT_CROSS))
868 .build()) {
869 @SuppressWarnings("unchecked")
870 @Override
871 FilesetTraversalParams create(Map<String, ?> kwArgs) throws Exception {
872 return FilesetTraversalParamsFactory.recursiveTraversalOfDirectory(
873 label((String) kwArgs.get("ownerLabel")),
874 getSourceArtifact((String) kwArgs.get("directoryToTraverse")),
875 new PathFragment((String) kwArgs.get("destPath")),
876 (Set<String>) kwArgs.get("excludes"),
877 ((SymlinkBehavior) kwArgs.get("symlinkBehaviorMode")),
878 (PackageBoundaryMode) kwArgs.get("pkgBoundaryMode"));
879 }
880 }.doTest();
881 }
882
Florian Weikert92b22362015-12-03 10:17:18 +0000883 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000884 public void testFingerprintOfPackageTraversal() throws Exception {
885 new FingerprintTester(
886 ImmutableMap.<String, Domain>builder()
887 .put("ownerLabel", notPartOfFingerprint("//foo", "//bar"))
888 .put("buildFile", partOfFingerprint("foo/BUILD", "bar/BUILD"))
889 .put("destPath", partOfFingerprint("out1", "out2"))
890 .put(
891 "excludes",
892 partOfFingerprint(ImmutableSet.<String>of(), ImmutableSet.<String>of("blah")))
893 .put(
894 "symlinkBehaviorMode",
895 partOfFingerprint(SymlinkBehavior.COPY, SymlinkBehavior.DEREFERENCE))
896 .put("pkgBoundaryMode", partOfFingerprint(CROSS, DONT_CROSS))
897 .build()) {
898 @SuppressWarnings("unchecked")
899 @Override
900 FilesetTraversalParams create(Map<String, ?> kwArgs) throws Exception {
901 return FilesetTraversalParamsFactory.recursiveTraversalOfPackage(
902 label((String) kwArgs.get("ownerLabel")),
903 getSourceArtifact((String) kwArgs.get("buildFile")),
904 new PathFragment((String) kwArgs.get("destPath")),
905 (Set<String>) kwArgs.get("excludes"),
906 ((SymlinkBehavior) kwArgs.get("symlinkBehaviorMode")),
907 (PackageBoundaryMode) kwArgs.get("pkgBoundaryMode"));
908 }
909 }.doTest();
910 }
911
Florian Weikert92b22362015-12-03 10:17:18 +0000912 @Test
Han-Wen Nienhuys81b90832015-10-26 16:57:27 +0000913 public void testFingerprintOfNestedTraversal() throws Exception {
914 FilesetTraversalParams n1 =
915 FilesetTraversalParamsFactory.fileTraversal(
916 /*ownerLabel=*/ label("//blah"),
917 /*fileToTraverse=*/ getSourceArtifact("blah/file.a"),
918 /*destPath=*/ new PathFragment("output-name"),
919 /*symlinkBehaviorMode=*/ SymlinkBehavior.COPY,
920 /*pkgBoundaryMode=*/ DONT_CROSS);
921
922 FilesetTraversalParams n2 =
923 FilesetTraversalParamsFactory.fileTraversal(
924 /*ownerLabel=*/ label("//blah"),
925 /*fileToTraverse=*/ getSourceArtifact("meow/file.b"),
926 /*destPath=*/ new PathFragment("output-name"),
927 /*symlinkBehaviorMode=*/ SymlinkBehavior.COPY,
928 /*pkgBoundaryMode=*/ DONT_CROSS);
929
930 new FingerprintTester(
931 ImmutableMap.<String, Domain>of(
932 "ownerLabel", notPartOfFingerprint("//foo", "//bar"),
933 "nested", partOfFingerprint(n1, n2),
934 "destDir", partOfFingerprint("out1", "out2"),
935 "excludes",
936 partOfFingerprint(ImmutableSet.<String>of(), ImmutableSet.<String>of("x")))) {
937 @SuppressWarnings("unchecked")
938 @Override
939 FilesetTraversalParams create(Map<String, ?> kwArgs) throws Exception {
940 return FilesetTraversalParamsFactory.nestedTraversal(
941 label((String) kwArgs.get("ownerLabel")),
942 (FilesetTraversalParams) kwArgs.get("nested"),
943 new PathFragment((String) kwArgs.get("destDir")),
944 (Set<String>) kwArgs.get("excludes"));
945 }
946 }.doTest();
947 }
948}