// Copyright 2022 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.query2.common;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.extensions.proto.ProtoTruth.assertThat;
import static org.junit.Assert.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.devtools.build.lib.bugreport.BugReporter;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.query2.engine.QueryException;
import com.google.devtools.build.lib.query2.engine.QueryExpression;
import com.google.devtools.build.lib.server.FailureDetails;
import com.google.devtools.build.lib.skyframe.DetailedException;
import com.google.devtools.build.lib.skyframe.TransitiveTargetKey;
import com.google.devtools.build.lib.util.DetailedExitCode;
import com.google.devtools.build.skyframe.CycleInfo;
import com.google.devtools.build.skyframe.ErrorInfo;
import com.google.devtools.build.skyframe.EvaluationContext;
import com.google.devtools.build.skyframe.EvaluationResult;
import com.google.devtools.build.skyframe.MemoizingEvaluator;
import com.google.devtools.build.skyframe.SkyFunctionException;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.testing.junit.testparameterinjector.TestParameter;
import com.google.testing.junit.testparameterinjector.TestParameterInjector;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

/** Tests for {@link QueryTransitivePackagePreloader}. */
@RunWith(TestParameterInjector.class)
public class QueryTransitivePackagePreloaderTest {
  private static final Label LABEL = Label.parseAbsoluteUnchecked("//my:label");
  private static final Label LABEL2 = Label.parseAbsoluteUnchecked("//my:label2");
  private static final Label LABEL3 = Label.parseAbsoluteUnchecked("//my:label3");
  private static final TransitiveTargetKey KEY = TransitiveTargetKey.of(LABEL);
  private static final TransitiveTargetKey KEY2 = TransitiveTargetKey.of(LABEL2);
  private static final TransitiveTargetKey KEY3 = TransitiveTargetKey.of(LABEL3);

  private static final ErrorInfo DETAILED_ERROR =
      ErrorInfo.fromException(
          new SkyFunctionException.ReifiedSkyFunctionException(
              new SkyFunctionException(
                  new MyDetailedException("bork"), SkyFunctionException.Transience.PERSISTENT) {}),
          /*isTransitivelyTransient=*/ false);
  private static final ErrorInfo UNDETAILED_ERROR =
      ErrorInfo.fromException(
          new SkyFunctionException.ReifiedSkyFunctionException(
              new SkyFunctionException(
                  new UndetailedException("bork"), SkyFunctionException.Transience.PERSISTENT) {}),
          /*isTransitivelyTransient=*/ false);
  private static final ErrorInfo CYCLE_ERROR =
      ErrorInfo.fromCycle(new CycleInfo(ImmutableList.of(KEY)));

  @Mock MemoizingEvaluator memoizingEvaluator;
  @Mock EvaluationContext.Builder contextBuilder;
  @Mock EvaluationContext context;
  private final BugReporter bugReporter = mock(BugReporter.class);

  private final QueryTransitivePackagePreloader underTest =
      new QueryTransitivePackagePreloader(
          () -> memoizingEvaluator, () -> contextBuilder, bugReporter);
  private AutoCloseable closeable;

  @Before
  public void setUpMocks() {
    closeable = MockitoAnnotations.openMocks(this);
    when(contextBuilder.setKeepGoing(ArgumentMatchers.anyBoolean())).thenReturn(contextBuilder);
    when(contextBuilder.setNumThreads(ArgumentMatchers.anyInt())).thenReturn(contextBuilder);
    when(contextBuilder.setEventHandler(ArgumentMatchers.any())).thenReturn(contextBuilder);
    when(contextBuilder.build()).thenReturn(context);
  }

  @After
  public void releaseMocks() throws Exception {
    verifyNoMoreInteractions(memoizingEvaluator);
    verifyNoMoreInteractions(bugReporter);
    closeable.close();
  }

  @Test
  public void preloadTransitiveTargets_noError() throws Exception {
    List<TransitiveTargetKey> roots = Lists.newArrayList(KEY);

    when(memoizingEvaluator.evaluate(roots, context))
        .thenReturn(EvaluationResult.builder().build());

    underTest.preloadTransitiveTargets(
        mock(ExtendedEventHandler.class),
        ImmutableList.of(LABEL),
        /*keepGoing=*/ true,
        1,
        /*callerForError=*/ null);

    verify(memoizingEvaluator).evaluate(roots, context);
  }

  @Test
  public void preloadTransitiveTargets_errorWithNullCallerKeepGoing_doesntCleanGraph()
      throws Exception {
    List<TransitiveTargetKey> roots = Lists.newArrayList(KEY);

    when(memoizingEvaluator.evaluate(roots, context))
        .thenReturn(EvaluationResult.builder().addError(KEY, UNDETAILED_ERROR).build());

    underTest.preloadTransitiveTargets(
        mock(ExtendedEventHandler.class),
        ImmutableList.of(LABEL),
        /*keepGoing=*/ true,
        1,
        /*callerForError=*/ null);

    verify(memoizingEvaluator).evaluate(roots, context);
  }

  @Test
  public void preloadTransitiveTargets_errorWithNullCallerKeepGoingCatastrophe_cleansGraph()
      throws Exception {
    List<TransitiveTargetKey> roots = Lists.newArrayList(KEY);

    when(memoizingEvaluator.evaluate(roots, context))
        .thenReturn(
            EvaluationResult.builder()
                .setCatastrophe(new UndetailedException("catas"))
                .addError(KEY, UNDETAILED_ERROR)
                .build());

    underTest.preloadTransitiveTargets(
        mock(ExtendedEventHandler.class),
        ImmutableList.of(LABEL),
        /*keepGoing=*/ true,
        1,
        /*callerForError=*/ null);

    verify(memoizingEvaluator).evaluate(roots, context);
    verify(memoizingEvaluator).evaluate(ImmutableList.of(), context);
  }

  @Test
  public void preloadTransitiveTargets_errorWithNullCallerNoKeepGoing_cleansGraph()
      throws Exception {
    List<TransitiveTargetKey> roots = Lists.newArrayList(KEY);

    when(memoizingEvaluator.evaluate(roots, context))
        .thenReturn(EvaluationResult.builder().addError(KEY, UNDETAILED_ERROR).build());

    underTest.preloadTransitiveTargets(
        mock(ExtendedEventHandler.class),
        ImmutableList.of(LABEL),
        /*keepGoing=*/ false,
        1,
        /*callerForError=*/ null);

    verify(memoizingEvaluator).evaluate(roots, context);
    verify(memoizingEvaluator).evaluate(ImmutableList.of(), context);
  }

  @Test
  public void preloadTransitiveTargets_detailedErrorWithCaller_throwsError(
      @TestParameter boolean keepGoing) throws Exception {
    List<TransitiveTargetKey> roots = Lists.newArrayList(KEY);

    when(memoizingEvaluator.evaluate(roots, context))
        .thenReturn(EvaluationResult.builder().addError(KEY, DETAILED_ERROR).build());

    var e =
        assertThrows(
            QueryException.class,
            () ->
                underTest.preloadTransitiveTargets(
                    mock(ExtendedEventHandler.class),
                    ImmutableList.of(LABEL),
                    keepGoing,
                    1,
                    /*callerForError=*/ mock(QueryExpression.class)));
    assertThat(e).hasMessageThat().contains("failed: bork");
    assertThat(e.getFailureDetail())
        .isSameInstanceAs(MyDetailedException.DETAILED_EXIT_CODE.getFailureDetail());

    verify(memoizingEvaluator).evaluate(roots, context);
  }

  @Test
  public void preloadTransitiveTargets_undetailedErrorWithCaller_throwsErrorAndFilesBugReport(
      @TestParameter boolean keepGoing) throws Exception {
    List<TransitiveTargetKey> roots = Lists.newArrayList(KEY);

    when(memoizingEvaluator.evaluate(roots, context))
        .thenReturn(EvaluationResult.builder().addError(KEY, UNDETAILED_ERROR).build());

    var e =
        assertThrows(
            QueryException.class,
            () ->
                underTest.preloadTransitiveTargets(
                    mock(ExtendedEventHandler.class),
                    ImmutableList.of(LABEL),
                    keepGoing,
                    1,
                    /*callerForError=*/ mock(QueryExpression.class)));
    assertThat(e).hasMessageThat().contains("failed: bork");
    assertThat(e.getFailureDetail())
        .comparingExpectedFieldsOnly()
        .isEqualTo(
            FailureDetails.FailureDetail.newBuilder()
                .setQuery(
                    FailureDetails.Query.newBuilder()
                        .setCode(FailureDetails.Query.Code.NON_DETAILED_ERROR)
                        .build())
                .build());

    verify(memoizingEvaluator).evaluate(roots, context);
    verify(bugReporter).sendBugReport(ArgumentMatchers.any());
  }

  @Test
  public void
      preloadTransitiveTargets_undetailedCatastropheAndDetailedExceptionWithCaller_throwsErrorAndFilesBugReport(
          @TestParameter boolean keepGoing) throws Exception {
    List<TransitiveTargetKey> roots = Lists.newArrayList(KEY);

    when(memoizingEvaluator.evaluate(roots, context))
        .thenReturn(
            EvaluationResult.builder()
                .addError(KEY, DETAILED_ERROR)
                .setCatastrophe(new UndetailedException("undetailed bok"))
                .build());

    var e =
        assertThrows(
            QueryException.class,
            () ->
                underTest.preloadTransitiveTargets(
                    mock(ExtendedEventHandler.class),
                    ImmutableList.of(LABEL),
                    keepGoing,
                    1,
                    /*callerForError=*/ mock(QueryExpression.class)));
    assertThat(e).hasMessageThat().contains("failed: undetailed bok");
    assertThat(e.getFailureDetail())
        .comparingExpectedFieldsOnly()
        .isEqualTo(
            FailureDetails.FailureDetail.newBuilder()
                .setQuery(
                    FailureDetails.Query.newBuilder()
                        .setCode(FailureDetails.Query.Code.NON_DETAILED_ERROR)
                        .build())
                .build());

    verify(memoizingEvaluator).evaluate(roots, context);
    verify(bugReporter).sendBugReport(ArgumentMatchers.any());
  }

  @Test
  public void preloadTransitiveTargets_undetailedAndDetailedExceptionsWithCaller_throwsError(
      @TestParameter boolean keepGoing, @TestParameter boolean includeCycle) throws Exception {
    List<TransitiveTargetKey> roots = Lists.newArrayList(KEY, KEY2, KEY3);

    EvaluationResult.Builder<SkyValue> resultBuilder =
        EvaluationResult.builder().addError(KEY, UNDETAILED_ERROR).addError(KEY2, DETAILED_ERROR);
    if (includeCycle) {
      resultBuilder.addError(KEY3, CYCLE_ERROR);
    }
    when(memoizingEvaluator.evaluate(roots, context)).thenReturn(resultBuilder.build());

    var e =
        assertThrows(
            QueryException.class,
            () ->
                underTest.preloadTransitiveTargets(
                    mock(ExtendedEventHandler.class),
                    ImmutableList.of(LABEL, LABEL2, LABEL3),
                    keepGoing,
                    1,
                    /*callerForError=*/ mock(QueryExpression.class)));
    assertThat(e).hasMessageThat().contains("failed: bork");
    assertThat(e.getFailureDetail())
        .isSameInstanceAs(MyDetailedException.DETAILED_EXIT_CODE.getFailureDetail());

    verify(memoizingEvaluator).evaluate(roots, context);
  }

  @Test
  public void preloadTransitiveTargets_cycleOnly_returns() throws Exception {
    List<TransitiveTargetKey> roots = Lists.newArrayList(KEY);

    when(memoizingEvaluator.evaluate(roots, context))
        .thenReturn(EvaluationResult.builder().addError(KEY, CYCLE_ERROR).build());

    underTest.preloadTransitiveTargets(
        mock(ExtendedEventHandler.class),
        ImmutableList.of(LABEL),
        /*keepGoing=*/ true,
        1,
        /*callerForError=*/ null);

    verify(memoizingEvaluator).evaluate(roots, context);
  }

  private static final class UndetailedException extends Exception {
    UndetailedException(String message) {
      super(message);
    }
  }

  private static final class MyDetailedException extends Exception implements DetailedException {
    private static final DetailedExitCode DETAILED_EXIT_CODE =
        DetailedExitCode.of(
            FailureDetails.FailureDetail.newBuilder()
                .setQuery(
                    FailureDetails.Query.newBuilder()
                        .setCode(FailureDetails.Query.Code.BUILD_FILE_ERROR))
                .build());

    MyDetailedException(String message) {
      super(message);
    }

    @Override
    public DetailedExitCode getDetailedExitCode() {
      return DETAILED_EXIT_CODE;
    }
  }
}
