// Copyright 2018 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.skyframe;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;

import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.Package;
import com.google.devtools.build.lib.skyframe.TransitiveBaseTraversalFunction.TargetAndErrorIfAnyImpl;
import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils;
import com.google.devtools.build.lib.util.GroupedList;
import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper;
import com.google.devtools.build.skyframe.EvaluationResult;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.ValueOrException2;
import com.google.devtools.build.skyframe.ValueOrUntypedException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import org.mockito.ArgumentMatchers;
import org.mockito.Mockito;

/** Test for {@link TransitiveTraversalFunction}. */
@RunWith(JUnit4.class)
public class TransitiveTraversalFunctionTest extends BuildViewTestCase {

  @Test
  public void noRepeatedLabelVisitationForTransitiveTraversalFunction() throws Exception {
    // Create a basic package with a target //foo:foo.
    Label label = Label.parseAbsolute("//foo:foo", ImmutableMap.of());
    scratch.file("foo/BUILD", "sh_library(name = '" + label.getName() + "')");
    Package pkg = loadPackage(label.getPackageIdentifier());
    TargetAndErrorIfAnyImpl targetAndErrorIfAny =
        new TargetAndErrorIfAnyImpl(
            /*packageLoadedSuccessfully=*/ true,
            /*errorLoadingTarget=*/ null,
            pkg.getTarget(label.getName()));
    TransitiveTraversalFunction function =
        new TransitiveTraversalFunction() {
          @Override
          TargetAndErrorIfAny loadTarget(Environment env, Label label) {
            return targetAndErrorIfAny;
          }
        };
    // Create the GroupedList saying we had already requested two targets the last time we called
    // #compute.
    GroupedListHelper<SkyKey> helper = new GroupedListHelper<>();
    SkyKey fakeDep1 = function.getKey(Label.parseAbsolute("//foo:bar", ImmutableMap.of()));
    SkyKey fakeDep2 = function.getKey(Label.parseAbsolute("//foo:baz", ImmutableMap.of()));
    helper.add(PackageValue.key(label.getPackageIdentifier()));
    helper.startGroup();
    // Note that these targets don't actually exist in the package we created initially. It doesn't
    // matter for the purpose of this test, the original package was just to create some objects
    // that we needed.
    helper.add(fakeDep1);
    helper.add(fakeDep2);
    helper.endGroup();
    GroupedList<SkyKey> groupedList = new GroupedList<>();
    groupedList.append(helper);
    AtomicBoolean wasOptimizationUsed = new AtomicBoolean(false);
    SkyFunction.Environment mockEnv = Mockito.mock(SkyFunction.Environment.class);
    when(mockEnv.getTemporaryDirectDeps()).thenReturn(groupedList);
    when(mockEnv.getValuesOrThrow(
            groupedList.get(1), NoSuchPackageException.class, NoSuchTargetException.class))
        .thenAnswer(
            (invocationOnMock) -> {
              wasOptimizationUsed.set(true);
              // It doesn't matter what this map is, we'll return false in the valuesMissing() call.
              return ImmutableMap.of();
            });
    when(mockEnv.valuesMissing()).thenReturn(true);

    // Run the compute function and check that we returned null.
    assertThat(function.compute(function.getKey(label), mockEnv)).isNull();

    // Verify that the mock was called with the arguments we expected.
    assertThat(wasOptimizationUsed.get()).isTrue();
  }

  @Test
  public void multipleErrorsForTransitiveTraversalFunction() throws Exception {
    Label label = Label.parseAbsolute("//foo:foo", ImmutableMap.of());
    scratch.file(
        "foo/BUILD", "sh_library(name = '" + label.getName() + "', deps = [':bar', ':baz'])");
    Package pkg = loadPackage(label.getPackageIdentifier());
    TargetAndErrorIfAnyImpl targetAndErrorIfAny =
        new TargetAndErrorIfAnyImpl(
            /*packageLoadedSuccessfully=*/ true,
            /*errorLoadingTarget=*/ null,
            pkg.getTarget(label.getName()));
    TransitiveTraversalFunction function =
        new TransitiveTraversalFunction() {
          @Override
          TargetAndErrorIfAny loadTarget(Environment env, Label label) {
            return targetAndErrorIfAny;
          }
        };
    SkyKey dep1 = function.getKey(Label.parseAbsolute("//foo:bar", ImmutableMap.of()));
    SkyKey dep2 = function.getKey(Label.parseAbsolute("//foo:baz", ImmutableMap.of()));
    ImmutableMap<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>>
        returnedDeps =
            ImmutableMap.of(dep1, makeException("bad bar"), dep2, makeException("bad baz"));
    SkyFunction.Environment mockEnv = Mockito.mock(SkyFunction.Environment.class);
    // Try two evaluations, with the environment reversing the order of the map it returns.
    when(mockEnv.getValuesOrThrow(
            ArgumentMatchers.any(),
            Mockito.eq(NoSuchPackageException.class),
            Mockito.eq(NoSuchTargetException.class)))
        .thenReturn(returnedDeps);
    when(mockEnv.valuesMissing()).thenReturn(false);

    assertThat(
            ((TransitiveTraversalValue) function.compute(function.getKey(label), mockEnv))
                .getErrorMessage())
        .isEqualTo("bad bar");
    ImmutableMap<SkyKey, ValueOrException2<NoSuchPackageException, NoSuchTargetException>>
        reversedDeps =
            ImmutableMap.of(dep2, makeException("bad baz"), dep1, makeException("bad bar"));
    when(mockEnv.getValuesOrThrow(
            ArgumentMatchers.any(),
            Mockito.eq(NoSuchPackageException.class),
            Mockito.eq(NoSuchTargetException.class)))
        .thenReturn(reversedDeps);
    assertThat(
            ((TransitiveTraversalValue) function.compute(function.getKey(label), mockEnv))
                .getErrorMessage())
        .isEqualTo("bad bar");
  }

  @Test
  public void selfErrorWins() throws Exception {
    Label label = Label.parseAbsolute("//foo:foo", ImmutableMap.of());
    scratch.file(
        "foo/BUILD", "sh_library(name = '" + label.getName() + "', deps = [':bar', ':baz'])");
    Package pkg = loadPackage(label.getPackageIdentifier());
    TargetAndErrorIfAnyImpl targetAndErrorIfAny =
        new TargetAndErrorIfAnyImpl(
            /*packageLoadedSuccessfully=*/ true,
            /*errorLoadingTarget=*/ new NoSuchTargetException("self error is long and last"),
            pkg.getTarget(label.getName()));
    TransitiveTraversalFunction function =
        new TransitiveTraversalFunction() {
          @Override
          TargetAndErrorIfAny loadTarget(Environment env, Label label) {
            return targetAndErrorIfAny;
          }
        };
    SkyKey dep = function.getKey(Label.parseAbsolute("//foo:bar", ImmutableMap.of()));
    SkyFunction.Environment mockEnv = Mockito.mock(SkyFunction.Environment.class);
    when(mockEnv.getValuesOrThrow(
            ArgumentMatchers.any(),
            Mockito.eq(NoSuchPackageException.class),
            Mockito.eq(NoSuchTargetException.class)))
        .thenReturn(ImmutableMap.of(dep, makeException("bad bar")));
    when(mockEnv.valuesMissing()).thenReturn(false);

    TransitiveTraversalValue transitiveTraversalValue =
        (TransitiveTraversalValue) function.compute(function.getKey(label), mockEnv);
    assertThat(transitiveTraversalValue.getErrorMessage()).isEqualTo("self error is long and last");
  }

  private static ValueOrException2<NoSuchPackageException, NoSuchTargetException> makeException(
      String errorMessage) {
    ValueOrUntypedException exn =
        ValueOrUntypedException.ofExn(new NoSuchTargetException(errorMessage));
    return ValueOrException2.fromUntypedException(
        exn, NoSuchPackageException.class, NoSuchTargetException.class);
  }

  /* Invokes the loading phase, using Skyframe. */
  private Package loadPackage(PackageIdentifier pkgid)
      throws InterruptedException, NoSuchPackageException {
    SkyKey key = PackageValue.key(pkgid);
    EvaluationResult<PackageValue> result =
        SkyframeExecutorTestUtils.evaluate(
            getSkyframeExecutor(), key, /*keepGoing=*/ false, reporter);
    if (result.hasError()) {
      throw (NoSuchPackageException) result.getError(key).getException();
    }
    return result.get(key).getPackage();
  }
}
