// Copyright 2021 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;

// For debugging, uncomment these and the call to setupLogging() below.
//
// import com.google.devtools.build.lib.blaze.BlazeRuntime;
// import java.util.logging.Level;

import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;

import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.BuildFailedException;
import com.google.devtools.build.lib.buildtool.util.BuildIntegrationTestCase;
import com.google.devtools.build.lib.events.Event;
import java.io.IOException;
import java.util.Iterator;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** A test of the semantics of the keepGoing flag: continue as much as possible after an error. */
@RunWith(JUnit4.class)
public class KeepGoingTest extends BuildIntegrationTestCase {

  @Before
  public final void addOptions() {
    addOptions("--keep_going");
  }

  private static String genrule(String name, String deps, int succeeds) {
    String out = name + ".out";
    String cmd = (succeeds != 0) ? "cp $(location in) $(location " + out + ")" : "exit 42";
    return "genrule(name='"
        + name
        + "', "
        + "           srcs=['in',"
        + deps
        + "], "
        + "           outs=['"
        + out
        + "'], "
        + "           cmd='"
        + cmd
        + "')\n";
  }

  private static final int A = 0x01;
  private static final int B = 0x02;
  private static final int C = 0x04;
  private static final int D = 0x08;
  private static final int E = 0x10;

  private static final String[] labels = {
    "//keepgoing:A", "//keepgoing:B", "//keepgoing:C", "//keepgoing:D", "//keepgoing:E"
  };

  // "mask" is a bitmask of rules that succeed.
  private void writeFiles(int mask) throws IOException {
    // A --> B --> C
    // |     +---> D
    // |
    // +---> E
    write(
        "keepgoing/BUILD",
        genrule("A", "'B','E'", mask & A)
            + genrule("B", "'C','D'", mask & B)
            + genrule("C", "", mask & C)
            + genrule("D", "", mask & D)
            + genrule("E", "", mask & E));

    write("keepgoing/in", "(input)");
  }

  // "mask" is a bitmask of rules that succeed.
  private void assertBuilt(int mask) throws Exception {
    for (int ii = 0; ii < labels.length; ii++) {
      assertOneBuilt(labels[ii], (mask & (1 << ii)) != 0);
    }
  }

  private void assertOneBuilt(String label, boolean shouldBeBuilt) throws Exception {
    Iterable<Artifact> files = getArtifacts(label);
    for (Artifact file : files) {
      boolean isActuallyBuilt = file.getPath().exists();
      if (file.getPath().exists() != shouldBeBuilt) {
        fail(
            file.prettyPrint()
                + ": shouldBeBuilt="
                + shouldBeBuilt
                + ", isActuallyBuilt="
                + isActuallyBuilt);
      }
    }
  }

  private void assertNoMoreEvents(Iterator<Event> events) {
    boolean ok = true;
    while (events.hasNext()) {
      System.err.println(events.next());
      ok = false;
    }
    assertThat(ok).isTrue();
  }

  // Build //keepgoing:A, expecting failure.  (The BuildResult instance is
  // subsequently available via getRequest() for later assertions.)
  private void buildA() throws Exception {
    BuildFailedException e =
        assertThrows(BuildFailedException.class, () -> buildTarget("//keepgoing:A"));
    assertThat(e).hasMessageThat().isNull();
  }

  /********************************************************************
   *                                                                  *
   *                         Actual tests...                          *
   *                                                                  *
   ********************************************************************/

  @Test
  public void testKeepGoingAfterCFails() throws Exception {
    // C fails due to error (logged).
    // B fails due to failed prereqs (logged).
    // A fails due to failed prereqs (logged).
    // D and E are built.
    // Then a BuildFailedException is thrown.
    writeFiles(A | B | D | E);
    buildA();

    Iterator<Event> errors = events.errors().iterator();
    assertThat(errors.next().getMessage())
        .containsMatch("Executing genrule //keepgoing:C failed: .*Exit 42.*");
    assertNoMoreEvents(errors);

    assertBuilt(D | E);
  }

  @Test
  public void testKeepGoingAfterDFails() throws Exception {
    // D fails due to error (logged).
    // B fails due to failed prereqs (logged).
    // A fails due to failed prereqs (logged).
    // C and E are built.
    // Then a BuildFailedException is thrown.
    writeFiles(A | B | C | E);
    buildA();

    Iterator<Event> errors = events.errors().iterator();
    assertThat(errors.next().getMessage())
        .containsMatch("Executing genrule //keepgoing:D failed: .*Exit 42.*");
    assertNoMoreEvents(errors);

    assertBuilt(C | E);
  }

  @Test
  public void testKeepGoingAfterCAndDFail() throws Exception {
    // C and D fail due to error (logged).
    // B fails due to failed prereqs (logged).
    // A fails due to failed prereqs (logged).
    // E is built.
    // Then a BuildFailedException is thrown.
    writeFiles(A | B | E);
    buildA();

    // C, D events are unordered:
    Iterator<Event> errors = events.errors().iterator();
    assertThat(errors.next().getMessage())
        .containsMatch("Executing genrule //keepgoing:(C|D) failed: .*Exit 42.*");
    assertThat(errors.next().getMessage())
        .containsMatch("Executing genrule //keepgoing:(C|D) failed: .*Exit 42.*");

    assertNoMoreEvents(errors);

    assertBuilt(E);
  }

  @Test
  public void testKeepGoingAfterEFails() throws Exception {
    // E fails due to error (logged).
    // A fails due to failed prereqs (logged).
    // B,C,D  are built.
    // Then a BuildFailedException is thrown.
    writeFiles(A | B | C | D);
    buildA();

    Iterator<Event> errors = events.errors().iterator();
    assertThat(errors.next().getMessage())
        .containsMatch("Executing genrule //keepgoing:E failed: .*Exit 42.*");
    assertNoMoreEvents(errors);

    assertBuilt(B | C | D);
  }

  // Regression test for b/8826301, incremental builder does not correctly set root actions.
  // Check that keep going works on second build. Note that this test failed non-deterministically
  // in b/8826301, because it depended on HashSet iteration order.
  @Test
  public void testKeepGoingOnSecondBuild() throws Exception {
    StringBuilder buildFile = new StringBuilder();
    buildFile
        .append("genrule(name='topgen', tools=[':badgen'], outs=['top.out'], ")
        .append("cmd='touch $@')\n")
        .append("genrule(name='badgen', executable=1, srcs=['badsrc.sh'], ")
        .append("outs=['bad.out'], cmd='bash $< >  $@', tools = [");
    // Make graph large so incremental dependency checker does graph culling, if enabled.
    for (int i = 0; i < 60; i++) {
      buildFile.append("':gen" + i + "', ");
    }
    buildFile.append("])\n");
    for (int i = 0; i < 60; i++) {
      buildFile
          .append("genrule(name='gen")
          .append(i)
          .append("', " + "outs=['gen")
          .append(i)
          .append(".out'], executable=1, cmd = 'echo \"#!/bin/true\" > $@')\n");
    }
    write("keepgoing/BUILD", buildFile.toString());
    write("keepgoing/badsrc.sh", "exit 0");
    buildTarget("//keepgoing:topgen");
    write("keepgoing/badsrc.sh", "exit 42");
    events.clear();
    BuildFailedException e =
        assertThrows(BuildFailedException.class, () -> buildTarget("//keepgoing:topgen"));
    assertThat(e).hasMessageThat().isNull();
    Iterator<Event> errors = events.errors().iterator();
    assertThat(errors.next().getMessage())
        .containsMatch("Executing genrule //keepgoing:badgen.* failed: .*Exit 42.*");
    assertNoMoreEvents(errors);
  }

  @Test
  public void testConfigurationErrorsAreToleratedWithKeepGoing() throws Exception {
    runtimeWrapper.addOptions("--experimental_builtins_injection_override=+cc_library");
    write("a/BUILD", "cc_library(name='a', srcs=['missing.foo'])");
    write("b/BUILD", "cc_library(name='b')");

    /**
     * Regression coverage for bug 1191396: "blaze build -k exits zero if execution succeeds, even
     * if there were analysis errors".
     */
    assertBuildFailedExceptionFromBuilding(
        "command succeeded, but not all targets were analyzed", "//a", "//b");
    events.assertContainsError(
        "in srcs attribute of cc_library rule //a:a: source file '//a:missing.foo' is misplaced"
            + " here");
    events.assertContainsInfo("Analysis succeeded for only 1 of 2 top-level targets");

    assertSameConfiguredTarget("//b:b");
  }

  @Test
  public void testKeepGoingAfterLoadingPhaseErrors() throws Exception {
    write("a/BUILD", "cc_library(name='a')");
    write("b/BUILD", "cc_library(name='b', deps = ['//missing:lib'])");

    assertBuildFailedExceptionFromBuilding(
        "command succeeded, but not all targets were analyzed", "//a", "//b"); //
    events.assertContainsError("no such package 'missing': BUILD file not found in any of the");

    assertSameConfiguredTarget("//a:a");
    events.assertContainsInfo(" succeeded for only 1 of ");
  }

  @Test
  public void testKeepGoingAfterTargetParsingErrors() throws Exception {
    write("a/BUILD", "cc_library(name='a', xyz)");
    write("b/BUILD", "cc_library(name='b', xyz)");
    write("b/b1/BUILD", "cc_library(name='b1')");
    write("b/b2/BUILD", "cc_library(name='b2', xyz)");

    assertBuildFailedExceptionFromBuilding(
        "command succeeded, but there were errors parsing the target pattern", "b/...", "//a");
    events.assertContainsWarning("Target pattern parsing failed.");

    assertSameConfiguredTarget("//b/b1");
  }

  @Test
  public void testKeepGoingAfterSchedulingDependencyMiddlemanFailure() throws Exception {
    write("foo/foo.cc", "int main() { return 0; }");
    write(
        "foo/BUILD",
        "cc_binary(name='foo', srcs=['foo.cc', 'gen.h'], malloc='system_malloc')",
        "cc_library(name='system_malloc', linkstatic=1)",
        "genrule(name='gen', srcs=[], outs=['gen.h'], cmd = 'exit 1')");

    assertThrows(BuildFailedException.class, () -> buildTarget("//foo:foo"));
  }

  private void assertSameConfiguredTarget(String label) throws Exception {
    assertThat(getOnlyElement(getResult().getSuccessfulTargets()))
        .isSameInstanceAs(getConfiguredTarget(label));
  }

  @Test
  public void testKeepGoingAfterAnalysisFailure() throws Exception {
    write(
        "analysiserror/failer.bzl",
        "def _failer_impl(ctx):",
        "  fail('BOOM!')",
        "",
        "failer = rule(implementation = _failer_impl)");
    write(
        "analysiserror/BUILD",
        "load(':failer.bzl', 'failer')",
        "genrule(name='gen', srcs=[], outs=['gen.h'], cmd='exit 1')",
        // The next line has an analysis failure: the xmb_lint rule is devoid of xmb files.
        "failer(name='foo')",
        "cc_library(name='bar')");

    assertBuildFailedExceptionFromBuilding(
        "command succeeded, but not all targets were analyzed",
        "//analysiserror:foo",
        "//analysiserror:bar");
    events.assertContainsError("Error in fail: BOOM!");

    assertSameConfiguredTarget("//analysiserror:bar");
  }

  private void assertBuildFailedExceptionFromBuilding(String msg, String... targets) {
    BuildFailedException e = assertThrows(BuildFailedException.class, () -> buildTarget(targets));
    assertThat(e).hasMessageThat().isEqualTo(msg);
    assertThat(getResult().getSuccess()).isFalse();
  }
}
