Skip to content

Commit 3aae024

Browse files
committed
Add test for source directory invalidation
1 parent 5d53bf6 commit 3aae024

File tree

2 files changed

+251
-0
lines changed

2 files changed

+251
-0
lines changed

src/test/java/com/google/devtools/build/lib/skyframe/BUILD

+19
Original file line numberDiff line numberDiff line change
@@ -1921,6 +1921,25 @@ java_test(
19211921
],
19221922
)
19231923

1924+
java_test(
1925+
name = "SourceDirectoryIntegrationTest",
1926+
srcs = ["SourceDirectoryIntegrationTest.java"],
1927+
jvm_flags = [
1928+
"-DBAZEL_TRACK_SOURCE_DIRECTORIES=1",
1929+
],
1930+
deps = [
1931+
"//src/main/java/com/google/devtools/build/lib:runtime",
1932+
"//src/main/java/com/google/devtools/build/lib/actions",
1933+
"//src/main/java/com/google/devtools/build/lib/events",
1934+
"//src/main/java/com/google/devtools/build/lib/vfs",
1935+
"//src/main/java/com/google/devtools/build/lib/vfs:pathfragment",
1936+
"//src/test/java/com/google/devtools/build/lib/buildtool/util",
1937+
"//third_party:guava",
1938+
"//third_party:junit4",
1939+
"//third_party:truth",
1940+
],
1941+
)
1942+
19241943
java_test(
19251944
name = "FileArtifactValueTest",
19261945
timeout = "short",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
// Copyright 2021 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+
package com.google.devtools.build.lib.skyframe;
15+
16+
import static org.junit.Assert.assertThrows;
17+
18+
import com.google.common.collect.ImmutableSet;
19+
import com.google.devtools.build.lib.actions.BuildFailedException;
20+
import com.google.devtools.build.lib.buildtool.util.BuildIntegrationTestCase;
21+
import com.google.devtools.build.lib.events.EventKind;
22+
import com.google.devtools.build.lib.vfs.FileSystemUtils;
23+
import com.google.devtools.build.lib.vfs.Path;
24+
import com.google.devtools.build.lib.vfs.PathFragment;
25+
import org.junit.Before;
26+
import org.junit.Ignore;
27+
import org.junit.Test;
28+
import org.junit.runner.RunWith;
29+
import org.junit.runners.JUnit4;
30+
31+
/** Integration test for invalidation of actions that consume source directories. */
32+
@RunWith(JUnit4.class)
33+
public final class SourceDirectoryIntegrationTest extends BuildIntegrationTestCase {
34+
35+
private Path sourceDir;
36+
37+
@Override
38+
protected ImmutableSet<EventKind> additionalEventsToCollect() {
39+
return ImmutableSet.of(EventKind.FINISH);
40+
}
41+
42+
@Before
43+
public void setUpGenrule() throws Exception {
44+
write(
45+
"foo/BUILD",
46+
"""
47+
genrule(
48+
name = "foo",
49+
srcs = ["dir"],
50+
outs = ["foo.out"],
51+
cmd = "touch $@",
52+
)
53+
""");
54+
55+
sourceDir = getWorkspace().getRelative("foo/dir");
56+
sourceDir.createDirectoryAndParents();
57+
FileSystemUtils.writeIsoLatin1(sourceDir.getRelative("file1"), "content");
58+
FileSystemUtils.writeIsoLatin1(sourceDir.getRelative("file2"), "content");
59+
FileSystemUtils.writeIsoLatin1(sourceDir.getRelative("file3"), "other content");
60+
sourceDir.getRelative("symlink").createSymbolicLink(PathFragment.create("file3"));
61+
sourceDir
62+
.getRelative("dangling_symlink")
63+
.createSymbolicLink(PathFragment.create("does_not_exist"));
64+
65+
Path subDir = sourceDir.getRelative("subdir");
66+
subDir.createDirectory();
67+
FileSystemUtils.writeIsoLatin1(subDir.getRelative("file1"), "content");
68+
FileSystemUtils.writeIsoLatin1(subDir.getRelative("file2"), "content");
69+
FileSystemUtils.writeIsoLatin1(subDir.getRelative("file3"), "other content");
70+
subDir.getRelative("symlink").createSymbolicLink(PathFragment.create("file3"));
71+
subDir
72+
.getRelative("dangling_symlink")
73+
.createSymbolicLink(PathFragment.create("does_not_exist"));
74+
75+
subDir.getRelative("nested").createDirectory();
76+
subDir.getRelative("nested2").createDirectory();
77+
subDir.getRelative("nested_non_empty").createDirectory();
78+
FileSystemUtils.writeIsoLatin1(subDir.getRelative("nested_non_empty/file1"), "content");
79+
80+
buildTarget("//foo");
81+
assertContainsEvent(events.collector(), "Executing genrule //foo:foo");
82+
83+
events.collector().clear();
84+
}
85+
86+
@Test
87+
public void nothingModified_doesNotInvalidateAction() throws Exception {
88+
assertNotInvalidatedByBuild();
89+
}
90+
91+
@Test
92+
public void touched_doesNotInvalidateAction() throws Exception {
93+
sourceDir.setLastModifiedTime(Path.NOW_SENTINEL_TIME);
94+
assertNotInvalidatedByBuild();
95+
}
96+
97+
@Test
98+
public void topLevelFileTouched_doesNotInvalidateAction() throws Exception {
99+
sourceDir.getRelative("file1").setLastModifiedTime(Path.NOW_SENTINEL_TIME);
100+
assertNotInvalidatedByBuild();
101+
}
102+
103+
@Test
104+
public void topLevelDirTouched_doesNotInvalidateAction() throws Exception {
105+
sourceDir.getRelative("subdir").setLastModifiedTime(Path.NOW_SENTINEL_TIME);
106+
assertNotInvalidatedByBuild();
107+
}
108+
109+
@Test
110+
public void nestedFileTouched_doesNotInvalidateAction() throws Exception {
111+
sourceDir.getRelative("subdir/file1").setLastModifiedTime(Path.NOW_SENTINEL_TIME);
112+
assertNotInvalidatedByBuild();
113+
}
114+
115+
@Test
116+
public void nestedDirTouched_doesNotInvalidateAction() throws Exception {
117+
sourceDir.getRelative("subdir/nested").setLastModifiedTime(Path.NOW_SENTINEL_TIME);
118+
assertNotInvalidatedByBuild();
119+
}
120+
121+
@Test
122+
public void topLevelFileDeleted_invalidatesAction() throws Exception {
123+
sourceDir.getRelative("file1").delete();
124+
assertInvalidatedByBuild();
125+
}
126+
127+
@Test
128+
public void nestedFileDeleted_invalidatesAction() throws Exception {
129+
sourceDir.getRelative("subdir/file1").delete();
130+
assertInvalidatedByBuild();
131+
}
132+
133+
@Test
134+
public void topLevelFileModified_invalidatesAction() throws Exception {
135+
FileSystemUtils.writeIsoLatin1(sourceDir.getRelative("file1"), "modified content");
136+
assertInvalidatedByBuild();
137+
}
138+
139+
@Test
140+
public void nestedFileModified_invalidatesAction() throws Exception {
141+
FileSystemUtils.writeIsoLatin1(sourceDir.getRelative("subdir/file1"), "modified content");
142+
assertInvalidatedByBuild();
143+
}
144+
145+
@Test
146+
public void topLevelFileAdded_invalidatesAction() throws Exception {
147+
FileSystemUtils.writeIsoLatin1(sourceDir.getRelative("new_file"), "modified content");
148+
assertInvalidatedByBuild();
149+
}
150+
151+
@Test
152+
public void nestedFileAdded_invalidatesAction() throws Exception {
153+
FileSystemUtils.writeIsoLatin1(sourceDir.getRelative("subdir/new_file"), "modified content");
154+
assertInvalidatedByBuild();
155+
}
156+
157+
@Test
158+
public void emptyDirDeleted_invalidatesAction() throws Exception {
159+
sourceDir.getRelative("subdir/nested").delete();
160+
assertInvalidatedByBuild();
161+
}
162+
163+
@Test
164+
public void fileReplacedByIdenticalSymlink_doesNotInvalidateAction() throws Exception {
165+
Path file = sourceDir.getRelative("file1");
166+
file.delete();
167+
file.createSymbolicLink(sourceDir.getRelative("file2"));
168+
assertNotInvalidatedByBuild();
169+
}
170+
171+
@Test
172+
public void fileReplacedByDifferentSymlink_invalidatesAction() throws Exception {
173+
Path file = sourceDir.getRelative("file1");
174+
file.delete();
175+
file.createSymbolicLink(sourceDir.getRelative("file3"));
176+
assertInvalidatedByBuild();
177+
}
178+
179+
@Test
180+
@Ignore("TODO(#25834)")
181+
public void emptyDirReplacedWithIdenticalSymlink_doesNotInvalidateAction() throws Exception {
182+
Path dir = sourceDir.getRelative("subdir/nested2");
183+
dir.delete();
184+
dir.createSymbolicLink(PathFragment.create("nested"));
185+
assertNotInvalidatedByBuild();
186+
}
187+
188+
@Test
189+
public void emptyDirReplacedWithDifferentSymlink_invalidatesAction() throws Exception {
190+
Path dir = sourceDir.getRelative("subdir/nested2");
191+
dir.delete();
192+
dir.createSymbolicLink(PathFragment.create("nested_non_empty"));
193+
assertInvalidatedByBuild();
194+
}
195+
196+
@Test
197+
public void infiniteSymlinkExpansion() throws Exception {
198+
Path dir = sourceDir.getRelative("subdir/nested2");
199+
dir.delete();
200+
dir.createSymbolicLink(PathFragment.create(".."));
201+
assertThrows(BuildFailedException.class, () -> buildTarget("//foo"));
202+
assertContainsEvent("infinite symlink expansion detected");
203+
assertContainsEvent("foo/dir/subdir/nested2");
204+
}
205+
206+
@Test
207+
@Ignore("TODO(#25834)")
208+
public void danglingSymlinkModified_invalidatesAction() throws Exception {
209+
FileSystemUtils.ensureSymbolicLink(
210+
sourceDir.getRelative("dangling_symlink"), PathFragment.create("still_does_not_exist"));
211+
assertInvalidatedByBuild();
212+
}
213+
214+
@Test
215+
@Ignore("TODO(#25834)")
216+
public void subPackageAdded_invalidatesAction() throws Exception {
217+
FileSystemUtils.touchFile(sourceDir.getRelative("subdir/BUILD"));
218+
assertInvalidatedByBuild();
219+
}
220+
221+
private static final String GENRULE_EVENT = "Executing genrule //foo:foo";
222+
223+
private void assertInvalidatedByBuild() throws Exception {
224+
buildTarget("//foo");
225+
assertContainsEvent(events.collector(), GENRULE_EVENT);
226+
}
227+
228+
private void assertNotInvalidatedByBuild() throws Exception {
229+
buildTarget("//foo");
230+
assertDoesNotContainEvent(events.collector(), GENRULE_EVENT);
231+
}
232+
}

0 commit comments

Comments
 (0)