// 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.collect.Iterables.getOnlyElement;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
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.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.buildtool.util.GoogleBuildIntegrationTestCase;
import com.google.devtools.build.lib.testutil.Suite;
import com.google.devtools.build.lib.testutil.TestSpec;
import com.google.devtools.build.lib.util.io.OutErr;
import com.google.devtools.build.lib.util.io.RecordingOutErr;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests that concern the transitive closure of data dependencies.
 * Regression testing for bug 1022571.
 */
@TestSpec(size = Suite.MEDIUM_TESTS)
@RunWith(JUnit4.class)
public abstract class TransitiveDataDependencyTest extends GoogleBuildIntegrationTestCase {

  /**
   * Hook for subclasses to define which executor we use.  (The two concrete
   * subclasses, {Sequential,Parallel}TransitiveDataDependencyTest are at the bottom of this
   * source file.)
   */
  protected abstract int numJobs();

  @Before
  public final void addJobNumberOption() throws Exception  {
    addOptions("--jobs", "" + numJobs());
  }

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

  @Test
  public void testTransitiveDataDepIsBuilt() throws Exception {
    write("data/BUILD",
          "cc_library(name = 'needsdata', data = [':data_bin'])",
          "cc_binary(name = 'data_bin', srcs = ['data_bin.c'])");
    write("data/data_bin.c", "int main() { return 0; }");

    buildTarget("//data:needsdata");
    ConfiguredTarget dataLibTarget = getConfiguredTarget("//data:data_bin");
    assertThat(getFilesToBuild(dataLibTarget).toList()).isNotEmpty();
    for (Artifact dataOut : getFilesToBuild(dataLibTarget).toList()) {
      assertWithMessage("Missing output: " + dataOut.getPath())
          .that(dataOut.getPath().exists())
          .isTrue();
    }
    assertSameConfiguredTarget("//data:needsdata");
  }

  @Test
  public void testMissingInputFile() throws Exception {
    write("data/BUILD",
        "cc_library(name = 'needsdata', data = [':data_file'])");

    RecordingOutErr recOutErr = new RecordingOutErr();
    OutErr origOutErr = this.outErr;
    this.outErr = recOutErr;

    // Remove this flag after fixing:
    // "Remove source artifacts from top-level artifacts in SkyframeExecutor#buildArtifacts"
    // We are adding information about //data:needdata to error message only if
    // ActionExecutionFunction has requested that missing artifact. But there is small chance
    // that ArtifactFunction of that missing artifact has thrown exception before that request.
    // In case of keep_going we can be sure that ActionExecutionFunction has made request.
    addOptions("--keep_going");
    try {
      buildTarget("//data:needsdata");
      fail();
    } catch (BuildFailedException e) {
      assertThat(recOutErr.errAsLatin1())
          .containsMatch("//data:needsdata: missing input file '//data:data_file'");
    } finally {
      this.outErr = origOutErr;
    }
    assertThat(getResult().getSuccess()).isFalse();
    assertThat(getResult().getSuccessfulTargets()).isEmpty();
  }

  @Test
  public void testMissingExportsFiles() throws Exception {
    write("data/BUILD", "exports_files(['nosuchfile'])");

    RecordingOutErr recOutErr = new RecordingOutErr();
    OutErr origOutErr = this.outErr;
    this.outErr = recOutErr;

    try {
      buildTarget("//data:nosuchfile");
      fail();
    } catch (BuildFailedException e) {
      assertThat(recOutErr.errAsLatin1()).containsMatch("missing input file '//data:nosuchfile'");
    } finally {
      this.outErr = origOutErr;
    }
    assertThat(getResult().getSuccess()).isFalse();
    assertThat(getResult().getSuccessfulTargets()).isEmpty();
  }


  @Test
  public void testMissingInputFilesKeepGoing() throws Exception {
    write("data/BUILD",
        "# Comment line",
        "cc_library(name = 'needsdata1', data = [':data_file1'])",
        "cc_library(name = 'needsdata2', data = [':data_file2'])");
    write("data/data_file2", "data_file2 exists");

    RecordingOutErr recOutErr = new RecordingOutErr();
    OutErr origOutErr = this.outErr;
    this.outErr = recOutErr;

    addOptions("--keep_going");
    try {
      buildTarget("//data:needsdata1", "//data:needsdata2");
      fail();
    } catch (BuildFailedException expected) {
      assertThat(recOutErr.errAsLatin1())
          .containsMatch(
              "data/BUILD:2:1: //data:needsdata1: missing input file '//data:data_file1'");
    } finally {
      this.outErr = origOutErr;
    }

    assertThat(getResult().getSuccess()).isFalse();
    assertSameConfiguredTarget("//data:needsdata2");
  }

  // Concrete implementations of this abstract test:

  /** Tests with 1 job. */
  @RunWith(JUnit4.class)
  public static class SequentialTransitiveDataDependencyTest extends TransitiveDataDependencyTest {
    @Override
    protected int numJobs() { return 0; }
  }

  /** Tests with 100 jobs. */
  @RunWith(JUnit4.class)
  public static class ParallelTransitiveDataDependencyTest extends TransitiveDataDependencyTest {
    @Override
    protected int numJobs() { return 100; }
  }
}
