// 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 org.junit.Assert.assertThrows;

import com.google.common.eventbus.Subscribe;
import com.google.devtools.build.lib.actions.BuildFailedException;
import com.google.devtools.build.lib.analysis.TargetCompleteEvent;
import com.google.devtools.build.lib.bazel.BazelWorkspaceStatusModule;
import com.google.devtools.build.lib.buildtool.util.BuildIntegrationTestCase;
import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.server.FailureDetails.Execution.Code;
import com.google.devtools.build.lib.server.FailureDetails.FailureDetail;
import com.google.devtools.build.lib.util.io.RecordingOutErr;
import com.google.devtools.build.lib.vfs.Path;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests related to "missing input file" errors. */
@RunWith(JUnit4.class)
public final class MissingInputActionTest extends BuildIntegrationTestCase {

  @Override
  protected BlazeModule getBuildInfoModule() {
    return new BazelWorkspaceStatusModule();
  }

  // Regression test for bug #904676: Blaze does not consider missing inputs
  // an error.
  @Test
  public void testNoInput() throws Exception {
    // Multiple missing inputs means error is non-deterministic in --nokeep_going case.
    this.addOptions("--keep_going");
    write(
        "dummy/BUILD",
        """
        genrule(name = 'dummy',
                srcs = ['in1', 'in2', 'in3'],
                outs = ['out1', 'out2'],
                cmd = '/bin/true')
        """);
    write("dummy/in1");

    assertMissingInputOnBuild("//dummy", 2);
    events.assertDoesNotContainEvent("missing input file '" + "//" + "dummy" + ":" + "in1'");
    events.assertContainsError("missing input file '" + "//" + "dummy" + ":" + "in2'");
    events.assertContainsError("missing input file '" + "//" + "dummy" + ":" + "in3'");
  }

  // The next two tests are inherently flakily successful with respect to the workspace status
  // action: even if we don't correctly suppress the workspace status action error message, we might
  // not have started it at all because Skyframe aborted quickly. That doesn't happen in practice,
  // though: the workspace status action starts right away.

  @Test
  public void testMissingInputRacesWithWorkspaceStatusAction() throws Exception {
    write(
        "dummy/BUILD",
        "genrule(name = 'dummy', srcs = ['in'], outs = ['out'], cmd = '/bin/false')");
    Path sleepPath = write("sleep.sh", "sleep 300");
    sleepPath.setExecutable(true);
    addOptions("--workspace_status_command=" + sleepPath.getPathString());
    for (int i = 0; i < 2; i++) {
      assertMissingInputOnBuild("//dummy", 1);
      events.assertContainsError(
          "dummy/BUILD:1:8: Executing genrule //dummy:dummy failed: missing input file"
              + " '//dummy:in'");
      events.assertContainsEventWithFrequency("missing input file", 1);
      events.assertDoesNotContainEvent("Failed to determine build info");
    }
  }

  @Test
  public void testMissingTopLevelInputRacesWithWorkspaceStatusAction() throws Exception {
    // Create a rule that exports a missing source file as a top-level artifact so that the missing
    // file will be detected by the TargetCompletion function, not an ActionExecution function.
    write(
        "foo/missing.bzl",
        """
        def _missing_impl(ctx):
            return DefaultInfo(files = depset(ctx.files.srcs))

        missing = rule(
                       implementation = _missing_impl,
                       attrs = { 'srcs': attr.label_list(allow_files = True) }
        )
        """);
    write(
        "foo/BUILD",
        """
        load('missing.bzl', 'missing')
        missing(name = 'foo', srcs = ['missing.sh'])
        """);
    Path sleepPath = write("sleep.sh", "sleep 300");
    sleepPath.setExecutable(true);
    addOptions("--workspace_status_command=" + sleepPath.getPathString());
    for (int i = 0; i < 2; i++) {
      assertMissingInputOnBuild("//foo:foo", 1);
      events.assertContainsError("foo/BUILD:2:8: //foo:foo: missing input file '//foo:missing.sh'");
      events.assertContainsEventWithFrequency("missing input file", 1);
      events.assertDoesNotContainEvent("Failed to determine build info");
    }
  }

  @Test
  public void testMissingTopLevelInput() throws Exception {
    // Create a rule that exports a missing source file as a top-level artifact so that the missing
    // file will be detected by the TargetCompletion function, not an ActionExecution function.
    write(
        "foo/missing.bzl",
        """
        def _missing_impl(ctx):
            return DefaultInfo(files = depset(ctx.files.srcs))

        missing = rule(
                       implementation = _missing_impl,
                       attrs = { 'srcs': attr.label_list(allow_files = True) }
        )
        """);
    write(
        "foo/BUILD",
        """
        load('missing.bzl', 'missing')
        missing(name = 'foo', srcs = ['missing.sh'])
        """);
    addOptions("--keep_going");
    assertMissingInputOnBuild("//foo:foo", 1);
    events.assertContainsError("foo/BUILD:2:8: //foo:foo: missing input file '//foo:missing.sh'");
    events.assertContainsEventWithFrequency("missing input file", 1);
  }

  private void assertMissingInputOnBuild(String label, int numMissing) {
    BuildFailedException e = assertThrows(BuildFailedException.class, () -> buildTarget(label));
    FailureDetail failureDetail = e.getDetailedExitCode().getFailureDetail();
    assertThat(failureDetail.getExecution().getCode()).isEqualTo(Code.SOURCE_INPUT_MISSING);
    String expected = numMissing + " input file(s) do not exist";
    events.assertContainsError(expected);
    events.assertContainsEventWithFrequency(expected, 1);
    events.assertContainsError(label);
  }

  @Test
  public void allErrorsAggregated() throws Exception {
    write(
        "foo/BUILD",
        """
        genrule(name = 'foo', srcs = [':in', ':genin'], outs = ['out'], cmd = 'touch $@')
        genrule(name = 'gen', outs = ['genin'], cmd = 'false')
        """);
    AtomicReference<TargetCompleteEvent> targetCompleteEventRef = new AtomicReference<>();
    runtimeWrapper.registerSubscriber(
        new Object() {
          @SuppressWarnings("unused")
          @Subscribe
          public void accept(TargetCompleteEvent event) {
            targetCompleteEventRef.set(event);
          }
        });
    RecordingOutErr outErr = new RecordingOutErr();
    this.outErr = outErr;
    addOptions("--keep_going");
    assertThrows(BuildFailedException.class, () -> buildTarget("//foo:foo"));
    assertThat(targetCompleteEventRef.get().getRootCauses().toList()).hasSize(1);
    assertThat(outErr.errAsLatin1()).contains("Executing genrule //foo:gen failed");
  }
}
