// Copyright 2020 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.buildtool;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
import static com.google.devtools.build.lib.testutil.BlazeTestUtils.createFilesetRule;
import static org.junit.Assert.assertThrows;

import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.actions.BuildFailedException;
import com.google.devtools.build.lib.actions.FileStateValue;
import com.google.devtools.build.lib.buildtool.util.GoogleBuildIntegrationTestCase;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.skyframe.DetailedException;
import com.google.devtools.build.lib.testutil.MoreAsserts;
import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.lib.unix.UnixFileSystem;
import com.google.devtools.build.lib.util.ExitCode;
import com.google.devtools.build.lib.util.io.RecordingOutErr;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.Dirent;
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.RootedPath;
import com.google.devtools.build.skyframe.NotifyingHelper;
import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import org.junit.Test;
import org.junit.runner.RunWith;

/**
 * Integration tests with a custom filesystem layer, for faking things like IOExceptions, on top of
 * the real unix filesystem (so we can execute actions).
 */
@RunWith(TestParameterInjector.class)
public class CustomRealFilesystemBuildIntegrationTest extends GoogleBuildIntegrationTestCase {

  private CustomRealFilesystem customFileSystem = null;

  @Override
  protected FileSystem createFileSystem() {
    if (customFileSystem == null) {
      customFileSystem = new CustomRealFilesystem(getDigestHashFunction());
    }
    return customFileSystem;
  }

  /** Tests that IOExceptions encountered while handling inputs are properly handled. */
  @Test
  public void testIOException() throws Exception {
    Path fooBuildFile = write("foo/BUILD", "sh_binary(name = 'foo', srcs = ['foo.sh'])");
    Path fooShFile = fooBuildFile.getParentDirectory().getRelative("foo.sh");
    customFileSystem.alwaysError(fooShFile);

    assertThrows(BuildFailedException.class, () -> buildTarget("//foo"));
    events.assertContainsError("//foo:foo: error reading file '//foo:foo.sh': nope");
  }

  /** Tests that IOExceptions encountered while handling inputs are properly handled. */
  @Test
  public void testIOExceptionMidLevel() throws Exception {
    Path fooBuildFile =
        write(
            "foo/BUILD",
            "sh_binary(name = 'foo', srcs = ['foo.sh'])",
            "genrule(name = 'top', srcs = [':foo'], outs = ['out'], cmd = 'touch $@')");
    Path fooShFile = fooBuildFile.getParentDirectory().getRelative("foo.sh");
    customFileSystem.alwaysError(fooShFile);

    assertThrows(BuildFailedException.class, () -> buildTarget("//foo:top"));
    events.assertContainsError(
        "Executing genrule //foo:top failed: error reading file '//foo:foo.sh': nope");
  }

  @Test
  public void globIOException() throws Exception {
    Path fooBuild = write("foo/BUILD", "exports_files(glob(['**/*.txt']))").getParentDirectory();
    Path badDir = fooBuild.getChild("bad");
    assertThat(badDir.createDirectory()).isTrue();
    customFileSystem.alwaysError(badDir);
    TargetParsingException e =
        assertThrows(TargetParsingException.class, () -> buildTarget("//foo:all"));
    assertThat(e)
        .hasMessageThat()
        .contains("no such package 'foo': error globbing [**/*.txt]: nope");
    assertThat(e.getDetailedExitCode().getFailureDetail().getPackageLoading().getCode())
        .isEqualTo(FailureDetails.PackageLoading.Code.GLOB_IO_EXCEPTION);
  }

  /**
   * Tests that IOExceptions encountered while handling non-mandatory inputs are properly handled.
   */
  @Test
  public void testIOException_nonMandatoryInputs() throws Exception {
    addOptions("--features=cc_include_scanning");
    write("foo/BUILD", "cc_library(name = 'foo', srcs = ['foo.cc'], hdrs_check = 'loose')");
    write("foo/foo.cc", "#include \"foo/foo.h\"");
    Path fooHFile = write("foo/foo.h", "//thisisacomment");
    customFileSystem.alwaysErrorAfter(fooHFile, 1);

    BuildFailedException e = assertThrows(BuildFailedException.class, () -> buildTarget("//foo"));
    assertThat(e.getDetailedExitCode().getExitCode()).isEqualTo(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
    events.assertContainsError(
        "foo/BUILD:1:11: Compiling foo/foo.cc failed: include scanning: Include scanning"
            + " IOException: nope");
  }

  @Test
  public void ioExceptionInSkyframeOptionalInput(@TestParameter boolean keepGoing)
      throws Exception {
    addOptions("--keep_going=" + keepGoing);
    addOptions("--features=cc_include_scanning");
    write("foo/BUILD", "cc_library(name = 'foo', srcs = ['foo.cc'], hdrs_check = 'loose')");
    Path ccFile = write("foo/foo.cc", "#include \"foo/foo.h\"");
    // Making the destination a symlink keeps the include scanner from populating the syscalls cache
    // before Skyframe gets a chance to stat the bad file.
    ccFile.getParentDirectory().getChild("foo.h").createSymbolicLink(PathFragment.create("bad.h"));
    Path badFile = write("foo/bad.h", "//ok contents");
    customFileSystem.alwaysError(badFile);

    BuildFailedException e = assertThrows(BuildFailedException.class, () -> buildTarget("//foo"));
    assertThat(e.getDetailedExitCode().getExitCode()).isEqualTo(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
    events.assertContainsError(
        "foo/BUILD:1:11: Compiling foo/foo.cc failed: error reading file 'foo/foo.h': nope");
  }

  @Test
  public void incrementalNonMandatoryInputIOException(@TestParameter boolean keepGoing)
      throws Exception {
    RecordingBugReporter bugReporter = recordBugReportsAndReinitialize();
    addOptions("--features=cc_include_scanning");
    addOptions("--keep_going=" + keepGoing);
    write("foo/BUILD", "cc_library(name = 'foo', srcs = ['foo.cc'], hdrs_check = 'loose')");
    write("foo/foo.cc", "#include \"foo/foo.h\"");
    Path fooHFile = write("foo/foo.h", "//thisisacomment");
    buildTarget("//foo");
    bugReporter.assertNoExceptions();

    write("foo/foo.cc", "//no include anymore");
    customFileSystem.alwaysError(fooHFile);
    if (keepGoing) {
      buildTarget("//foo");
      bugReporter.assertNoExceptions();
    } else {
      RecordingOutErr outErr = new RecordingOutErr();
      this.outErr = outErr;
      BuildFailedException e = assertThrows(BuildFailedException.class, () -> buildTarget("//foo"));
      assertDetailedExitCodeIsSourceIOFailure(e);
      Throwable cause = bugReporter.getFirstCause();
      assertThat(cause).hasMessageThat().isEqualTo("error reading file 'foo/foo.h': nope");
      assertDetailedExitCodeIsSourceIOFailure(cause);
      assertThat(outErr.errAsLatin1()).contains("error reading file 'foo/foo.h': nope");
    }
  }

  @Test
  public void unusedInputIOExceptionIncremental(@TestParameter boolean keepGoing) throws Exception {
    RecordingBugReporter bugReporter = recordBugReportsAndReinitialize();
    addOptions("--keep_going=" + keepGoing);
    write(
        "foo/pruning.bzl",
        "def _impl(ctx):",
        "  inputs = ctx.attr.inputs.files",
        "  output = ctx.actions.declare_file(ctx.label.name + '.out')",
        "  unused_file = ctx.actions.declare_file(ctx.label.name + '.unused')",
        "  ctx.actions.run(",
        "    inputs = inputs,",
        "    outputs = [output, unused_file],",
        "    arguments = [output.path, unused_file.path] + [f.path for f in inputs.to_list()],",
        "    executable = ctx.executable.executable,",
        "    unused_inputs_list = unused_file,",
        "  )",
        "  return DefaultInfo(files = depset([output]))",
        "",
        "build_rule = rule(",
        "  attrs = {",
        "    'inputs': attr.label(allow_files = True),",
        "    'executable': attr.label(executable = True, allow_files = True, cfg = 'host'),",
        "  },",
        "  implementation = _impl,",
        ")");
    Path unusedSh =
        write("foo/all_unused.sh", "touch $1", "shift", "unused=$1", "shift", "echo $@ > $unused");
    unusedSh.setExecutable(true);
    write(
        "foo/BUILD",
        "load('//foo:pruning.bzl', 'build_rule')",
        "build_rule(name = 'prune', inputs = ':unused.txt', executable = ':all_unused.sh')");
    Path unusedPath = write("foo/unused.txt");
    buildTarget("//foo:prune");
    bugReporter.assertNoExceptions();

    customFileSystem.alwaysError(unusedPath);
    if (keepGoing) {
      buildTarget("//foo:prune");
      bugReporter.assertNoExceptions();
    } else {
      RecordingOutErr outErr = new RecordingOutErr();
      this.outErr = outErr;
      BuildFailedException e =
          assertThrows(BuildFailedException.class, () -> buildTarget("//foo:prune"));
      assertDetailedExitCodeIsSourceIOFailure(e);
      Throwable cause = bugReporter.getFirstCause();
      assertThat(cause).hasMessageThat().isEqualTo("error reading file '//foo:unused.txt': nope");
      assertDetailedExitCodeIsSourceIOFailure(cause);
      assertThat(outErr.errAsLatin1()).contains("error reading file '//foo:unused.txt': nope");
    }
  }

  private static final FailureDetails.FailureDetail SOURCE_IO_FAILURE =
      FailureDetails.FailureDetail.newBuilder()
          .setExecution(
              FailureDetails.Execution.newBuilder()
                  .setCode(FailureDetails.Execution.Code.SOURCE_INPUT_IO_EXCEPTION))
          .build();

  private static void assertDetailedExitCodeIsSourceIOFailure(Throwable exception) {
    assertThat(exception).isInstanceOf(DetailedException.class);
    assertThat(((DetailedException) exception).getDetailedExitCode().getFailureDetail())
        .comparingExpectedFieldsOnly()
        .isEqualTo(SOURCE_IO_FAILURE);
  }

  /** Tests that IOExceptions encountered when not all discovered deps are done are handled. */
  @Test
  public void testIOException_missingNonMandatoryInput() throws Exception {
    addOptions("--features=cc_include_scanning");
    Path fooBuildFile =
        write("foo/BUILD", "cc_library(name = 'foo', srcs = ['foo.cc'], hdrs_check = 'loose')");
    write("foo/foo.cc", "#include \"foo/error.h\"", "#include \"foo/other.h\"");
    Path errorHFile = fooBuildFile.getParentDirectory().getRelative("error.h");
    Path otherHFile = fooBuildFile.getParentDirectory().getRelative("other.h");
    writeAbsolute(errorHFile, "//thisisacomment");
    writeAbsolute(otherHFile, "//thisisacomment");
    customFileSystem.alwaysErrorAfter(errorHFile, 1);
    getSkyframeExecutor()
        .getEvaluatorForTesting()
        .injectGraphTransformerForTesting(
            NotifyingHelper.makeNotifyingTransformer(
                (key, type, order, context) -> {
                  if (key.functionName().equals(FileStateValue.FILE_STATE)
                      && ((RootedPath) key.argument())
                          .getRootRelativePath()
                          .getPathString()
                          .endsWith("foo/other.h")) {
                    try {
                      Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
                      throw new IllegalStateException("Should have been interrupted by failure");
                    } catch (InterruptedException e) {
                      Thread.currentThread().interrupt();
                    }
                  }
                }));

    BuildFailedException e = assertThrows(BuildFailedException.class, () -> buildTarget("//foo"));
    assertThat(e.getDetailedExitCode().getExitCode()).isEqualTo(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
    events.assertContainsError(
        "foo/BUILD:1:11: Compiling foo/foo.cc failed: include scanning: Include scanning"
            + " IOException: nope");
  }

  /**
   * Tests that IOExceptions encountered while handling non-mandatory generated inputs are properly
   * handled.
   */
  @Test
  public void testIOException_nonMandatoryGeneratedInputs() throws Exception {
    addOptions("--features=cc_include_scanning");
    write(
        "bar/BUILD",
        "cc_library(",
        "   name = 'bar',",
        "   hdrs = ['bar.h'],",
        "   srcs = ['bar.cc'],",
        "   visibility = ['//foo:__pkg__']",
        ")",
        "genrule(name = 'bar-gen', srcs = ['in.txt'], outs = ['bar.h'], "
            + "cmd = \"cp $(SRCS) $(OUTS)\")");
    write("foo/BUILD",
        "cc_binary(name = 'foo', srcs = ['foo.cc'], deps = [':mid'])",
        "cc_library(name = 'mid', deps = ['//bar'])");
    write("foo/foo.cc",
        "#include \"bar/bar.h\"",
        "int main() { return f(); }");

    write("bar/bar.cc", "int f() { return 0; }");
    write("bar/in.txt", "int f(); // 0");

    // On an incremental skyframe build, the output file from a genrule is accessed 6 times via this
    // test's instrumented methods.
    //   FilesystemValueChecker
    //   ActionCacheChecker#needToExecute
    //   Path#getDigest (from ActionCacheChecker)
    //   Internal remote execution client to check if symlink
    //   SpawnIncludeScanner#shouldparseRemotely
    //   IncludeParser#extractInclusions

    int numAccessesOnIncrementalBuildWithChange = 6;
    buildTarget("//bar");
    Path barHOutputPath = Iterables.getOnlyElement(getArtifacts("//bar:bar.h")).getPath();
    customFileSystem.alwaysErrorAfter(barHOutputPath, numAccessesOnIncrementalBuildWithChange);
    write("bar/in.txt", "int f(); // 1");
    buildTarget("//foo");
    // Check that the expected number of stats were made on the generated file (note that this
    // sufficiently confirms that the genrule was rerun).
    // TODO(bazel-team): This test currently isn't super useful because Skyframe doesn't declare
    // deps on undeclared generated headers (it only does so for source headers). If we change this
    // behavior, we can test it by having the final stat done on the output file (on a clean build)
    // fail, but all the previous ones done (e.g. during the genrule execution) succeed. But for now
    // we just check the exact number of stats done.
    assertThat(customFileSystem.getNumCallsUntilError(barHOutputPath)).isEqualTo(0);
    customFileSystem.alwaysErrorAfter(barHOutputPath, numAccessesOnIncrementalBuildWithChange);
    write("bar/in.txt", "int f(); // 2");
    buildTarget("//foo");
    assertThat(customFileSystem.getNumCallsUntilError(barHOutputPath)).isEqualTo(0);
  }

  @Test
  public void ioExceptionReadingBuildFileForDiscoveredInput() throws Exception {
    addOptions("--features=cc_include_scanning");
    write("hello/BUILD", "cc_library(name = 'hello', srcs = ['hello.cc'], hdrs_check = 'loose')");
    write("hello/hello.cc", "#include \"hello/subdir/undeclared.h\"");
    Path header = write("hello/subdir/undeclared.h");
    Path buildFile = header.getParentDirectory().getChild("BUILD");
    // Error unfortunately not noticed when we find header directly.
    customFileSystem.alwaysError(buildFile);
    addOptions("--discard_analysis_cache"); // Fall back to action cache on next build.
    buildTarget("//hello:hello");
    BuildFailedException e =
        assertThrows(BuildFailedException.class, () -> buildTarget("//hello:hello"));
    MoreAsserts.assertContainsEvent(
        events.collector(),
        Pattern.compile(
            "^ERROR.*Compiling hello/hello.cc failed: Unable to resolve hello/subdir/undeclared.h"
                + " as an artifact: no such package 'hello/subdir': IO errors while looking for"
                + " BUILD file reading .*hello/subdir/BUILD: nope"));
    assertThat(e.getDetailedExitCode().getFailureDetail())
        .comparingExpectedFieldsOnly()
        .isEqualTo(
            FailureDetails.FailureDetail.newBuilder()
                .setIncludeScanning(
                    FailureDetails.IncludeScanning.newBuilder()
                        .setCode(FailureDetails.IncludeScanning.Code.SYSTEM_PACKAGE_LOAD_FAILURE)
                        .setPackageLoadingCode(
                            FailureDetails.PackageLoading.Code.OTHER_IO_EXCEPTION))
                .build());
  }

  @Test
  public void inconsistentExceptionReadingBuildFileForDiscoveredInput() throws Exception {
    addOptions("--features=cc_include_scanning");
    write("hello/BUILD", "cc_library(name = 'hello', srcs = ['hello.cc'], hdrs_check = 'loose')");
    write("hello/hello.cc", "#include \"hello/subdir/undeclared.h\"");
    write("hello/subdir/undeclared.h");
    addOptions("--discard_analysis_cache"); // Fall back to action cache on next build.
    buildTarget("//hello:hello");
    Path buildFile = write("hello/subdir/BUILD");
    customFileSystem.errorInsideStat(buildFile, 0);
    BuildFailedException e =
        assertThrows(BuildFailedException.class, () -> buildTarget("//hello:hello"));
    MoreAsserts.assertContainsEvent(
        events.collector(),
        Pattern.compile(
            ".*Compiling hello/hello.cc failed: Unable to resolve hello/subdir/undeclared.h as an"
                + " artifact: Inconsistent filesystem operations. 'stat' said"
                + " .*/hello/subdir/BUILD is a file but then we later encountered error 'nope for"
                + " .*/hello/subdir/BUILD' which indicates that .*/hello/subdir/BUILD is no longer"
                + " a file.*"));
    events.assertContainsError("hello/subdir/BUILD ");
    assertThat(e.getDetailedExitCode().getFailureDetail())
        .comparingExpectedFieldsOnly()
        .isEqualTo(
            FailureDetails.FailureDetail.newBuilder()
                .setIncludeScanning(
                    FailureDetails.IncludeScanning.newBuilder()
                        .setCode(FailureDetails.IncludeScanning.Code.SYSTEM_PACKAGE_LOAD_FAILURE)
                        .setPackageLoadingCode(
                            FailureDetails.PackageLoading.Code
                                .PERSISTENT_INCONSISTENT_FILESYSTEM_ERROR))
                .build());
  }

  @Test
  public void treeArtifactIOExceptionTopLevel() throws Exception {
    write(
        "foo/tree.bzl",
        "def _tree_impl(ctx):",
        "    tree = ctx.actions.declare_directory('mytree.cc')",
        "    ctx.actions.run_shell(outputs = [tree], command = 'mkdir -p %s && touch %s/one.cc' %"
            + " (tree.path, tree.path))",
        "    return [DefaultInfo(files = depset([tree]))]",
        "",
        "mytree = rule(implementation = _tree_impl)");
    write(
        "foo/BUILD",
        "load('//foo:tree.bzl', 'mytree')",
        "mytree(name = 'tree')",
        "cc_library(name = 'lib', srcs = [':tree'])");
    customFileSystem.errorOnDirectory("mytree");
    BuildFailedException e =
        assertThrows(BuildFailedException.class, () -> buildTarget("//foo:lib"));
    assertThat(e.getDetailedExitCode().getExitCode()).isEqualTo(ExitCode.BUILD_FAILURE);
    events.assertContainsError(
        "foo/BUILD:3:11: Failed to create output directory for TreeArtifact"
            + " blaze-out/k8-fastbuild/bin/foo/_pic_objs/lib/mytree: nope");
  }

  @Test
  public void treeArtifactIOExceptionMidLevel() throws Exception {
    write(
        "foo/tree.bzl",
        "def _tree_impl(ctx):",
        "    tree = ctx.actions.declare_directory('mytree.cc')",
        "    ctx.actions.run_shell(outputs = [tree], command = 'mkdir -p %s && touch %s/one.cc' %"
            + " (tree.path, tree.path))",
        "    return [DefaultInfo(files = depset([tree]))]",
        "",
        "mytree = rule(implementation = _tree_impl)");
    write(
        "foo/BUILD",
        "load('//foo:tree.bzl', 'mytree')",
        "mytree(name = 'tree')",
        "cc_library(name = 'lib', srcs = [':tree'])",
        "genrule(name = 'top', srcs = [':lib'], outs = ['out'], cmd = 'touch $@')");
    customFileSystem.errorOnDirectory("mytree");
    BuildFailedException e =
        assertThrows(BuildFailedException.class, () -> buildTarget("//foo:top"));
    assertThat(e.getDetailedExitCode().getExitCode()).isEqualTo(ExitCode.BUILD_FAILURE);
    events.assertContainsError(
        "foo/BUILD:3:11: Failed to create output directory for TreeArtifact"
            + " blaze-out/k8-fastbuild/bin/foo/_pic_objs/lib/mytree: nope");
  }

  @Test
  public void filesetIOException() throws Exception {
    write("foo/BUILD");
    Path filePath = write("foo/subdir/file");
    // Violating best practices, this doesn't explicitly list the file underneath //foo that it
    // wants, since then foo would have to expose that file as a target, leading to foo/subdir
    // being listed (and cached in Skyframe) during the analysis phase, not the execution phase.
    write(
        "fileset/BUILD",
        createFilesetRule("fileset", "fs_out", "FilesetEntry (srcdir = '//foo', destdir = 'x')"));
    customFileSystem.alwaysError(filePath.getParentDirectory());
    BuildFailedException e =
        assertThrows(BuildFailedException.class, () -> buildTarget("//fileset"));
    assertThat(e.getDetailedExitCode().getExitCode()).isEqualTo(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
    events.assertContainsError(
        "Traversing Fileset trees to write manifest fileset/fileset.fileset_manifest failed: Error"
            + " while traversing directory foo/subdir: nope");
  }

  @Test
  public void filesetIOExceptionInBuildFile() throws Exception {
    // Violating best practices, this doesn't explicitly list the file underneath //foo that it
    // wants, since then foo would have to expose that file as a target, leading to foo/subdir
    // being listed (and cached in Skyframe) during the analysis phase, not the execution phase.
    Path packageBuildFile =
        write(
            "fileset/BUILD",
            createFilesetRule("fileset", "fs_out", "FilesetEntry (srcdir = 'foo', destdir = 'x')"));
    Path packageDirectory = packageBuildFile.getParentDirectory();
    Path subdir = packageDirectory.getRelative("foo/bar");
    subdir.createDirectoryAndParents();
    customFileSystem.alwaysError(subdir.getChild("BUILD"));
    BuildFailedException e =
        assertThrows(BuildFailedException.class, () -> buildTarget("//fileset"));
    assertThat(e.getDetailedExitCode().getExitCode()).isEqualTo(ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
    events.assertContainsError(
        "Traversing Fileset trees to write manifest fileset/fileset.fileset_manifest failed: Error"
            + " while traversing directory fileset/foo/bar: no such package 'fileset/foo/bar': IO"
            + " errors while looking for BUILD file");
  }

  private void runIoExceptionInTopLevelSource() throws Exception {
    write(
        "foo/rule.bzl",
        "def _impl(ctx):",
        "  return [DefaultInfo(files = depset([], transitive = [dep[DefaultInfo].files for dep in"
            + " ctx.attr.srcs]))]",
        "",
        "top_source = rule(",
        "    implementation = _impl,",
        "    attrs = {'srcs': attr.label_list(allow_files = True)}",
        ")");
    Path buildFile =
        write(
            "foo/BUILD",
            "load(':rule.bzl', 'top_source')",
            "top_source(name = 'foo', srcs = ['error.in', 'missing.in'])");
    customFileSystem.alwaysError(buildFile.getParentDirectory().getChild("error.in"));
    assertThrows(BuildFailedException.class, () -> buildTarget("//foo:foo"));
  }

  @Test
  public void ioExceptionInTopLevelSource_keepGoing() throws Exception {
    addOptions("--keep_going");
    runIoExceptionInTopLevelSource();
    events.assertContainsError(
        "foo/BUILD:2:11: //foo:foo: error reading file '//foo:error.in': nope");
    events.assertContainsError("foo/BUILD:2:11: //foo:foo: missing input file '//foo:missing.in'");
    events.assertContainsError("2 input file(s) are in error or do not exist");
  }

  @Test
  public void ioExceptionInTopLevelSource_noKeepGoing() throws Exception {
    runIoExceptionInTopLevelSource();
    MoreAsserts.assertContainsEvent(
        events.collector(),
        Pattern.compile(
            ".*foo/BUILD:2:11: //foo:foo: (error reading file '//foo:error.in': nope|missing input"
                + " file '//foo:missing.in')"));
    MoreAsserts.assertContainsEvent(
        events.collector(),
        Pattern.compile(
            ".*(1 input file\\(s\\) (are in error|do not exist)|2 input file\\(s\\) are in error"
                + " or do not exist)"));
  }

  private void runMissingFileAndIoException() throws Exception {
    Path buildFile =
        write(
            "foo/BUILD",
            "genrule(name = 'foo', srcs = ['error.in', 'missing.in'], outs = ['out'], cmd = 'touch"
                + " $@')");
    customFileSystem.alwaysError(buildFile.getParentDirectory().getChild("error.in"));
    assertThrows(BuildFailedException.class, () -> buildTarget("//foo:foo"));
  }

  @Test
  public void missingFileAndIoException_keepGoing() throws Exception {
    addOptions("--keep_going");
    runMissingFileAndIoException();
    events.assertContainsError(
        "foo/BUILD:1:8: Executing genrule //foo:foo failed: error reading file '//foo:error.in':"
            + " nope");
  }

  @Test
  public void missingFileAndIoException_noKeepGoing() throws Exception {
    runMissingFileAndIoException();
    MoreAsserts.assertContainsEvent(
        events.collector(),
        Pattern.compile(
            ".*foo/BUILD:1:8: Executing genrule //foo:foo failed: (error reading file"
                + " '//foo:error.in': nope|missing input file '//foo:missing.in')"));
    MoreAsserts.assertContainsEvent(
        events.collector(),
        Pattern.compile(
            ".*(1 input file\\(s\\) (are in error|do not exist)|2 input file\\(s\\) are in error"
                + " or do not exist)"));
  }

  private static class CustomRealFilesystem extends UnixFileSystem {
    private final Map<PathFragment, Integer> badPaths = new HashMap<>();
    private final Map<PathFragment, Integer> statBadPaths = new HashMap<>();
    private final Set<String> createDirectoryErrorNames = new HashSet<>();

    private CustomRealFilesystem(DigestHashFunction digestHashFunction) {
      super(digestHashFunction, /*hashAttributeName=*/ "");
    }

    void alwaysError(Path path) {
      alwaysErrorAfter(path, 0);
    }

    void alwaysErrorAfter(Path path, int numCalls) {
      badPaths.put(path.asFragment(), numCalls);
    }

    void errorOnDirectory(String baseName) {
      createDirectoryErrorNames.add(baseName);
    }

    void errorInsideStat(Path path, int numCalls) {
      statBadPaths.put(path.asFragment(), numCalls);
    }

    int getNumCallsUntilError(Path path) {
      return badPaths.getOrDefault(path.asFragment(), 0);
    }

    private static boolean shouldThrowExn(PathFragment path, Map<PathFragment, Integer> paths) {
      if (paths.containsKey(path)) {
        Integer numCallsRemaining = paths.get(path);
        if (numCallsRemaining <= 0) {
          return true;
        } else {
          paths.put(path, numCallsRemaining - 1);
        }
      }
      return false;
    }

    private synchronized void maybeThrowExn(PathFragment path) throws IOException {
      if (shouldThrowExn(path, badPaths)) {
        throw new IOException("nope");
      }
    }

    @Override
    protected FileStatus statNullable(PathFragment path, boolean followSymlinks) {
      try {
        maybeThrowExn(path);
      } catch (IOException e) {
        return null;
      }
      return super.statNullable(path, followSymlinks);
    }

    @Override
    protected FileStatus statIfFound(PathFragment path, boolean followSymlinks) throws IOException {
      maybeThrowExn(path);
      FileStatus fileStatus = super.statIfFound(path, followSymlinks);
      return shouldThrowExn(path, statBadPaths) ? new ThrowingFileStatus(path) : fileStatus;
    }

    @Override
    protected UnixFileStatus statInternal(PathFragment path, boolean followSymlinks)
        throws IOException {
      maybeThrowExn(path);
      return super.statInternal(path, followSymlinks);
    }

    @Override
    protected Collection<Dirent> readdir(PathFragment path, boolean followSymlinks)
        throws IOException {
      maybeThrowExn(path);
      return super.readdir(path, followSymlinks);
    }

    @Override
    public void createDirectoryAndParents(PathFragment path) throws IOException {
      if (createDirectoryErrorNames.contains(path.getBaseName())) {
        throw new IOException("nope");
      }
      super.createDirectoryAndParents(path);
    }

    @Override
    protected PathFragment readSymbolicLinkUnchecked(PathFragment path) throws IOException {
      maybeThrowExn(path);
      return super.readSymbolicLinkUnchecked(path);
    }

    @Override
    protected InputStream createFileInputStream(PathFragment path) throws IOException {
      maybeThrowExn(path);
      return super.createFileInputStream(path);
    }

    private static class ThrowingFileStatus implements FileStatus {
      private final PathFragment path;

      ThrowingFileStatus(PathFragment path) {
        this.path = path;
      }

      @Override
      public boolean isFile() {
        return true;
      }

      @Override
      public boolean isDirectory() {
        return false;
      }

      @Override
      public boolean isSymbolicLink() {
        return false;
      }

      @Override
      public boolean isSpecialFile() {
        return false;
      }

      @Override
      public long getSize() throws IOException {
        throw new IOException("nope for " + path);
      }

      @Override
      public long getLastModifiedTime() throws IOException {
        throw new IOException("nope for " + path);
      }

      @Override
      public long getLastChangeTime() throws IOException {
        throw new IOException("nope for " + path);
      }

      @Override
      public long getNodeId() throws IOException {
        throw new IOException("nope for " + path);
      }
    }
  }
}
