Don't bother getting the not-real FileStateValue for a path whose parent doesn't exist. In addition to saving a filesystem operation, this removes a source of a potential filesystem inconsistency. -- MOS_MIGRATED_REVID=136355008
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java index 5257324..6308953 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/FileFunctionTest.java
@@ -888,22 +888,13 @@ } @Test - public void testFilesystemInconsistencies_ParentDoesntExistAndChildIsSymlink() throws Exception { - symlink("a/b", "doesntmatter"); - // Our custom filesystem says "a/b" exists but "a" does not exist. + public void testDoesntStatChildIfParentDoesntExist() throws Exception { + // Our custom filesystem says "a" does not exist, so FileFunction shouldn't bother trying to + // think about "a/b". Test for this by having a stat of "a/b" fail with an io error, and + // observing that we don't encounter the error. fs.stubStat(path("a"), null); - SequentialBuildDriver driver = makeDriver(); - SkyKey skyKey = skyKey("a/b"); - EvaluationResult<FileValue> result = - driver.evaluate( - ImmutableList.of(skyKey), false, DEFAULT_THREAD_COUNT, NullEventHandler.INSTANCE); - assertTrue(result.hasError()); - ErrorInfo errorInfo = result.getError(skyKey); - assertThat(errorInfo.getException()).isInstanceOf(InconsistentFilesystemException.class); - assertThat(errorInfo.getException().getMessage()) - .contains( - "/root/a/b was a symlink to doesntmatter but others made us think it was a " - + "nonexistent path"); + fs.stubStatError(path("a/b"), new IOException("ouch!")); + assertThat(valueForPath(path("a/b")).exists()).isFalse(); } @Test @@ -1639,8 +1630,9 @@ private class CustomInMemoryFs extends InMemoryFileSystem { - private Map<Path, FileStatus> stubbedStats = Maps.newHashMap(); - private Map<Path, IOException> stubbedFastDigestErrors = Maps.newHashMap(); + private final Map<Path, FileStatus> stubbedStats = Maps.newHashMap(); + private final Map<Path, IOException> stubbedStatErrors = Maps.newHashMap(); + private final Map<Path, IOException> stubbedFastDigestErrors = Maps.newHashMap(); public CustomInMemoryFs(ManualClock manualClock) { super(manualClock); @@ -1667,8 +1659,15 @@ stubbedStats.put(path, stubbedResult); } + public void stubStatError(Path path, IOException error) { + stubbedStatErrors.put(path, error); + } + @Override public FileStatus stat(Path path, boolean followSymlinks) throws IOException { + if (stubbedStatErrors.containsKey(path)) { + throw stubbedStatErrors.get(path); + } if (stubbedStats.containsKey(path)) { return stubbedStats.get(path); }
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java index 9175145..3c960df 100644 --- a/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java +++ b/src/test/java/com/google/devtools/build/lib/skyframe/PackageFunctionTest.java
@@ -252,7 +252,6 @@ Path bazDir = bazFile.getParentDirectory(); Path barDir = bazDir.getParentDirectory(); - long bazFileNodeId = bazFile.stat().getNodeId(); // Our custom filesystem says "foo/bar/baz" does not exist but it also says that "foo/bar" // has a child directory "baz". fs.stubStat(bazDir, null); @@ -265,9 +264,7 @@ new Dirent("baz", Dirent.Type.DIRECTORY)))); differencer.inject(ImmutableMap.of(DirectoryListingValue.key(barDirRootedPath), barDirListing)); SkyKey skyKey = PackageValue.key(PackageIdentifier.parse("@//foo")); - String expectedMessage = "Some filesystem operations implied /workspace/foo/bar/baz/baz.sh was " - + "a regular file with size of 0 and mtime of 0 and nodeId of " + bazFileNodeId + " and " - + "mtime of 0 but others made us think it was a nonexistent path"; + String expectedMessage = "/workspace/foo/bar/baz is no longer an existing directory"; EvaluationResult<PackageValue> result = SkyframeExecutorTestUtils.evaluate( getSkyframeExecutor(), skyKey, /*keepGoing=*/false, reporter); assertTrue(result.hasError());