Add a test for handling of `InconsistentFilesystemException` from underlying packages in `PrepareDepsOfTargetsUnderDirectoryFunction`.
This adds coverage for the crash fixed in https://github.com/bazelbuild/bazel/commit/43a5a035572c1fb52155c8957f80f29617fa81a4.
PiperOrigin-RevId: 436348711
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/BUILD b/src/test/java/com/google/devtools/build/lib/skyframe/BUILD
index faff3c5..211193b 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/BUILD
@@ -378,6 +378,8 @@
srcs = ["PrepareDepsOfTargetsUnderDirectoryFunctionTest.java"],
deps = [
"//src/main/java/com/google/devtools/build/lib/cmdline",
+ "//src/main/java/com/google/devtools/build/lib/io:inconsistent_filesystem_exception",
+ "//src/main/java/com/google/devtools/build/lib/io:process_package_directory_exception",
"//src/main/java/com/google/devtools/build/lib/pkgcache",
"//src/main/java/com/google/devtools/build/lib/skyframe:collect_packages_under_directory_value",
"//src/main/java/com/google/devtools/build/lib/skyframe:prepare_deps_of_targets_under_directory_value",
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunctionTest.java
index 7d42e06..16901aa 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/PrepareDepsOfTargetsUnderDirectoryFunctionTest.java
@@ -25,8 +25,13 @@
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.RepositoryName;
+import com.google.devtools.build.lib.io.InconsistentFilesystemException;
+import com.google.devtools.build.lib.io.ProcessPackageDirectoryException;
import com.google.devtools.build.lib.pkgcache.FilteringPolicies;
import com.google.devtools.build.lib.pkgcache.FilteringPolicy;
+import com.google.devtools.build.lib.vfs.DelegateFileSystem;
+import com.google.devtools.build.lib.vfs.FileStatus;
+import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
@@ -36,6 +41,9 @@
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.WalkableGraph;
import java.io.IOException;
+import java.util.concurrent.ConcurrentHashMap;
+import javax.annotation.Nullable;
+import org.junit.After;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
@@ -46,6 +54,29 @@
@RunWith(JUnit4.class)
public class PrepareDepsOfTargetsUnderDirectoryFunctionTest extends BuildViewTestCase {
+ private final ConcurrentHashMap<PathFragment, FileStatus> injectedStats =
+ new ConcurrentHashMap<>();
+
+ @Override
+ protected FileSystem createFileSystem() {
+ return new DelegateFileSystem(super.createFileSystem()) {
+ @Override
+ protected FileStatus statIfFound(PathFragment path, boolean followSymlinks)
+ throws IOException {
+ @Nullable FileStatus injectedStat = injectedStats.remove(path);
+ if (injectedStat != null) {
+ return injectedStat;
+ }
+ return super.statIfFound(path, followSymlinks);
+ }
+ };
+ }
+
+ @After
+ public void checkNoInjectedStatsLeft() {
+ assertThat(injectedStats).isEmpty();
+ }
+
private static SkyKey createCollectPackagesKey(
Path root, PathFragment rootRelativePath, ImmutableSet<PathFragment> excludedPaths) {
RootedPath rootedPath = RootedPath.toRootedPath(Root.fromPath(root), rootRelativePath);
@@ -74,17 +105,23 @@
RepositoryName.MAIN, rootedPath, excludedPaths, filteringPolicy);
}
- private EvaluationResult<?> getEvaluationResult(SkyKey... keys) throws InterruptedException {
+ private EvaluationResult<PrepareDepsOfTargetsUnderDirectoryValue> getAndCheckEvaluationResult(
+ SkyKey... keys) throws InterruptedException {
+ EvaluationResult<PrepareDepsOfTargetsUnderDirectoryValue> evaluationResult =
+ getEvaluationResult(keys);
+ assertThatEvaluationResult(evaluationResult).hasNoError();
+ return evaluationResult;
+ }
+
+ private EvaluationResult<PrepareDepsOfTargetsUnderDirectoryValue> getEvaluationResult(
+ SkyKey... keys) throws InterruptedException {
EvaluationContext evaluationContext =
EvaluationContext.newBuilder()
.setKeepGoing(false)
.setNumThreads(SequencedSkyframeExecutor.DEFAULT_THREAD_COUNT)
.setEventHandler(reporter)
.build();
- EvaluationResult<PrepareDepsOfTargetsUnderDirectoryValue> evaluationResult =
- skyframeExecutor.getEvaluator().evaluate(ImmutableList.copyOf(keys), evaluationContext);
- assertThatEvaluationResult(evaluationResult).hasNoError();
- return evaluationResult;
+ return skyframeExecutor.getEvaluator().evaluate(ImmutableList.copyOf(keys), evaluationContext);
}
@Test
@@ -94,7 +131,7 @@
// When package "a" is evaluated,
SkyKey key = createPrepDepsKey(rootDirectory, PathFragment.create("a"));
- EvaluationResult<?> evaluationResult = getEvaluationResult(key);
+ EvaluationResult<?> evaluationResult = getAndCheckEvaluationResult(key);
WalkableGraph graph = Preconditions.checkNotNull(evaluationResult.getWalkableGraph());
// Then the TransitiveTraversalValue for "@//a:a" is evaluated,
@@ -124,7 +161,7 @@
PathFragment.create("a"),
ImmutableSet.of(),
FilteringPolicies.FILTER_TESTS);
- EvaluationResult<?> evaluationResult = getEvaluationResult(key);
+ EvaluationResult<?> evaluationResult = getAndCheckEvaluationResult(key);
WalkableGraph graph = Preconditions.checkNotNull(evaluationResult.getWalkableGraph());
// Then the TransitiveTraversalValue for "@//a:a" is not evaluated,
@@ -163,7 +200,7 @@
SkyKey collectkey =
createCollectPackagesKey(
rootDirectory, PathFragment.create("a"), ImmutableSet.of(excludedPathFragment));
- EvaluationResult<?> evaluationResult = getEvaluationResult(key, collectkey);
+ EvaluationResult<?> evaluationResult = getAndCheckEvaluationResult(key, collectkey);
CollectPackagesUnderDirectoryValue value =
(CollectPackagesUnderDirectoryValue)
evaluationResult
@@ -216,7 +253,7 @@
SkyKey key = createPrepDepsKey(rootDirectory, PathFragment.create("a"), excludedPaths);
SkyKey collectKey =
createCollectPackagesKey(rootDirectory, PathFragment.create("a"), excludedPaths);
- EvaluationResult<?> evaluationResult = getEvaluationResult(key, collectKey);
+ EvaluationResult<?> evaluationResult = getAndCheckEvaluationResult(key, collectKey);
CollectPackagesUnderDirectoryValue value =
(CollectPackagesUnderDirectoryValue)
evaluationResult
@@ -259,4 +296,18 @@
// And no package is under "a/b/d".
assertThat(abValue.getSubdirectoryTransitivelyContainsPackagesOrErrors().get(abd)).isFalse();
}
+
+ @Test
+ public void testInconsistentFileSystemExceptionFailsWithProperError() throws Exception {
+ Path buildFile = scratch.file("a/b/BUILD", "sh_library(name='b')");
+ SkyKey key = createPrepDepsKey(rootDirectory, PathFragment.create("a"));
+ // Inject a "file" stat for "a/b" directory to trigger a InconsistentFilesystemException.
+ injectedStats.put(buildFile.getParentDirectory().asFragment(), buildFile.stat());
+
+ EvaluationResult<?> evaluationResult = getEvaluationResult(key);
+
+ Exception e = evaluationResult.getError(key).getException();
+ assertThat(e).isInstanceOf(ProcessPackageDirectoryException.class);
+ assertThat(e).hasCauseThat().isInstanceOf(InconsistentFilesystemException.class);
+ }
}