// Copyright 2014 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.analysis.test;

import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.devtools.build.lib.actions.ActionContext;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.SpawnResult;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.view.test.TestStatus.TestResultData;
import java.io.IOException;
import java.util.List;
import javax.annotation.Nullable;

/**
 * A context for the execution of test actions ({@link TestRunnerAction}).
 */
public interface TestActionContext extends ActionContext {
  TestRunnerSpawn createTestRunnerSpawn(
      TestRunnerAction testRunnerAction, ActionExecutionContext actionExecutionContext)
      throws ExecException, InterruptedException;

  /** Returns whether test_keep_going is enabled. */
  boolean isTestKeepGoing();

  /**
   * Returns {@code true} to indicate that exclusive tests should be treated as regular parallel
   * tests.
   *
   * <p>Returning {@code true} may make sense for certain forced remote test execution strategies
   * where running tests in sequence would be wasteful.
   */
  default boolean forceParallelTestExecution() {
    return false;
  }

  /** Creates a cached test result. */
  TestResult newCachedTestResult(Path execRoot, TestRunnerAction action, TestResultData cached)
      throws IOException;

  /**
   * Returns a listenable future that is unique for any given combination of owner and shard number,
   * i.e., that is cached across different runs within the same shard of the same target. This is to
   * facilitate cross-action cancellation - if {@code runs_per_test} and {@code
   * runs_per_test_detects_flake} are both set, then it is sufficient to have a single passing
   * result per shard, and any concurrent actions can be cancelled.
   *
   * <p>Note that the output files of a test are named after the owner, which guarantees that there
   * are no two tests with the same owner.
   */
  @Nullable
  ListenableFuture<Void> getTestCancelFuture(ActionOwner owner, int shardNum);

  /**
   * An object representing an individual test attempt result. Note that {@link TestRunnerSpawn} is
   * generic in a subtype of this type; this interface only provide a tiny amount of generic
   * top-level functionality necessary to share code between the different {@link TestActionContext}
   * implementations.
   */
  interface TestAttemptResult {
    /** Test attempt result, splitting failures into permanent vs retriable. */
    enum Result {
      /** Test attempt successful. */
      PASSED,
      /** Test failed, potentially due to test flakiness, can be retried. */
      FAILED_CAN_RETRY,
      /** Permanent failure. */
      FAILED;

      boolean canRetry() {
        return this == FAILED_CAN_RETRY;
      }
    }

    /** Returns the overall test result. */
    Result result();

    /** Returns a list of spawn results for this test attempt. */
    ImmutableList<SpawnResult> spawnResults();
  }

  /**
   * An object representing a failed non-final attempt. This is only used for tests that are run
   * multiple times. At this time, Bazel retries tests until the first passed attempt, or until the
   * number of retries is exhausted - whichever comes first. This interface represents the result
   * from a previous attempt, but never the final attempt, even if unsuccessful.
   */
  interface FailedAttemptResult {}

  /** A continuation that represents a single test attempt. */
  abstract class TestAttemptContinuation {
    public static TestAttemptContinuation of(TestAttemptResult testAttemptResult) {
      return new Finished(testAttemptResult);
    }

    /** Returns true if this is a final result. */
    public boolean isDone() {
      return false;
    }

    /** Returns a future representing any ongoing concurrent work, or {@code null} otherwise. */
    @Nullable
    public abstract ListenableFuture<?> getFuture();

    /** Performs the next step in the process of executing the test attempt. */
    public abstract TestAttemptContinuation execute()
        throws InterruptedException, IOException, ExecException;

    /** Returns the final result. */
    public TestAttemptResult get() {
      throw new IllegalStateException();
    }

    /** Represents a finished test attempt. */
    private static final class Finished extends TestAttemptContinuation {
      private final TestAttemptResult testAttemptResult;

      private Finished(TestAttemptResult testAttemptResult) {
        this.testAttemptResult = testAttemptResult;
      }

      @Override
      public boolean isDone() {
        return true;
      }

      @Override
      public ListenableFuture<?> getFuture() {
        return Futures.immediateFuture(null);
      }

      @Override
      public TestAttemptContinuation execute() {
        return this;
      }

      @Override
      public TestAttemptResult get() {
        return testAttemptResult;
      }
    }
  }

  /** A delegate to run a test. This may include running multiple spawns, renaming outputs, etc. */
  interface TestRunnerSpawn {
    ActionExecutionContext getActionExecutionContext();

    /**
     * Begin the test attempt execution. This may block until the test attempt is complete and
     * return a completed result, or it may return a continuation with a non-null future
     * representing asynchronous execution.
     */
    TestAttemptContinuation beginExecution() throws InterruptedException, IOException;

    /**
     * After the first attempt has run, this method is called to determine the maximum number of
     * attempts for this test.
     */
    int getMaxAttempts(TestAttemptResult firstTestAttemptResult);

    /** Rename the output files if the test attempt failed, and post the test attempt result. */
    FailedAttemptResult finalizeFailedTestAttempt(TestAttemptResult testAttemptResult, int attempt)
        throws IOException;

    /** Post the final test result based on the last attempt and the list of failed attempts. */
    void finalizeTest(
        TestAttemptResult lastTestAttemptResult, List<FailedAttemptResult> failedAttempts)
        throws IOException;

    /** Post the final test result based on the last attempt and the list of failed attempts. */
    void finalizeCancelledTest(List<FailedAttemptResult> failedAttempts) throws IOException;

    /**
     * Return a {@link TestRunnerSpawn} object if test fallback is enabled, or {@code null}
     * otherwise. Test fallback is a feature to allow a test to run with one strategy until the max
     * attempts are exhausted and then run with another strategy for another set of attempts. This
     * is rarely used, and should ideally be removed.
     */
    default TestRunnerSpawn getFallbackRunner() throws ExecException {
      return null;
    }
  }
}
