// Copyright 2015 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 com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.graph.ImmutableGraph;
import com.google.common.util.concurrent.Callables;
import com.google.devtools.build.lib.actions.AbstractAction;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionExecutionException;
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionLookupData;
import com.google.devtools.build.lib.actions.ActionResult;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Executor;
import com.google.devtools.build.lib.actions.FileStateValue;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.actions.util.DummyExecutor;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.testutil.TimestampGranularityUtils;
import com.google.devtools.build.lib.util.CrashFailureDetails;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.ErrorInfo;
import com.google.devtools.build.skyframe.EvaluationProgressReceiver;
import com.google.devtools.build.skyframe.EvaluationProgressReceiver.EvaluationState;
import com.google.devtools.build.skyframe.GraphInconsistencyReceiver;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.SkyframeIterableResult;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;
import javax.annotation.Nullable;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link SkyframeAwareAction}. */
@RunWith(JUnit4.class)
public class SkyframeAwareActionTest extends TimestampBuilderTestCase {
  private Builder builder;
  private Executor executor;
  private TrackingEvaluationProgressReceiver progressReceiver;

  @Before
  public final void createBuilder() throws Exception {
    progressReceiver = new TrackingEvaluationProgressReceiver();
    builder =
        createBuilder(
            inMemoryCache,
            1,
            /*keepGoing=*/ false,
            progressReceiver,
            GraphInconsistencyReceiver.THROWING);
  }

  @Before
  public final void createExecutor() throws Exception {
    executor = new DummyExecutor(fileSystem, rootDirectory);
  }

  private static final class TrackingEvaluationProgressReceiver
      implements EvaluationProgressReceiver {

    public static final class InvalidatedKey {
      public final SkyKey skyKey;
      public final InvalidationState state;

      InvalidatedKey(SkyKey skyKey, InvalidationState state) {
        this.skyKey = skyKey;
        this.state = state;
      }

      @Override
      public boolean equals(Object obj) {
        return obj instanceof InvalidatedKey
            && this.skyKey.equals(((InvalidatedKey) obj).skyKey)
            && this.state.equals(((InvalidatedKey) obj).state);
      }

      @Override
      public int hashCode() {
        return Objects.hashCode(skyKey, state);
      }
    }

    private static final class EvaluatedEntry {
      public final SkyKey skyKey;
      final EvaluationSuccessState successState;
      public final EvaluationState state;

      EvaluatedEntry(SkyKey skyKey, EvaluationSuccessState successState, EvaluationState state) {
        this.skyKey = skyKey;
        this.successState = successState;
        this.state = state;
      }

      @Override
      public boolean equals(Object obj) {
        return obj instanceof EvaluatedEntry
            && this.skyKey.equals(((EvaluatedEntry) obj).skyKey)
            && this.successState.equals(((EvaluatedEntry) obj).successState)
            && this.state.equals(((EvaluatedEntry) obj).state);
      }

      @Override
      public int hashCode() {
        return Objects.hashCode(skyKey, successState, state);
      }
    }

    public final Set<InvalidatedKey> invalidated = Sets.newConcurrentHashSet();
    public final Set<SkyKey> enqueued = Sets.newConcurrentHashSet();
    public final Set<EvaluatedEntry> evaluated = Sets.newConcurrentHashSet();

    public void reset() {
      invalidated.clear();
      enqueued.clear();
      evaluated.clear();
    }

    public boolean wasInvalidated(SkyKey skyKey) {
      for (InvalidatedKey e : invalidated) {
        if (e.skyKey.equals(skyKey)) {
          return true;
        }
      }
      return false;
    }

    public EvaluatedEntry getEvalutedEntry(SkyKey forKey) {
      for (EvaluatedEntry e : evaluated) {
        if (e.skyKey.equals(forKey)) {
          return e;
        }
      }
      return null;
    }

    @Override
    public void invalidated(SkyKey skyKey, InvalidationState state) {
      invalidated.add(new InvalidatedKey(skyKey, state));
    }

    @Override
    public void enqueueing(SkyKey skyKey) {
      enqueued.add(skyKey);
    }

    @Override
    public void evaluated(
        SkyKey skyKey,
        @Nullable SkyValue value,
        @Nullable ErrorInfo error,
        Supplier<EvaluationSuccessState> evaluationSuccessState,
        EvaluationState state) {
      evaluated.add(new EvaluatedEntry(skyKey, evaluationSuccessState.get(), state));
    }
  }

  /** A mock action that counts how many times it was executed. */
  private static class ExecutionCountingAction extends AbstractAction {
    private final AtomicInteger executionCounter;

    ExecutionCountingAction(Artifact input, Artifact output, AtomicInteger executionCounter) {
      super(
          ActionsTestUtil.NULL_ACTION_OWNER,
          NestedSetBuilder.create(Order.STABLE_ORDER, input),
          ImmutableSet.of(output));
      this.executionCounter = executionCounter;
    }

    @Override
    public ActionResult execute(ActionExecutionContext actionExecutionContext)
        throws ActionExecutionException, InterruptedException {
      executionCounter.incrementAndGet();

      // This action first reads its input file (there can be only one). For the purpose of these
      // tests we assume that the input file is short, maybe just 10 bytes long.
      byte[] input = new byte[10];
      int inputLen = 0;
      try (InputStream in = getInputs().getSingleton().getPath().getInputStream()) {
        inputLen = in.read(input);
      } catch (IOException e) {
        throw new ActionExecutionException(
            e, this, false, CrashFailureDetails.detailedExitCodeForThrowable(e));
      }

      // This action then writes the contents of the input to the (only) output file, and appends an
      // extra "x" character too.
      try (OutputStream out = getPrimaryOutput().getPath().getOutputStream()) {
        out.write(input, 0, inputLen);
        out.write('x');
      } catch (IOException e) {
        throw new ActionExecutionException(
            e, this, false, CrashFailureDetails.detailedExitCodeForThrowable(e));
      }
      return ActionResult.EMPTY;
    }

    @Override
    public String getMnemonic() {
      return "ExecutionCountingAction";
    }

    @Override
    protected void computeKey(
        ActionKeyContext actionKeyContext,
        @Nullable Artifact.ArtifactExpander artifactExpander,
        Fingerprint fp) {
      fp.addString(getPrimaryOutput().getExecPathString());
      fp.addInt(executionCounter.get());
    }
  }

  private static class ExecutionCountingCacheBypassingAction extends ExecutionCountingAction {
    ExecutionCountingCacheBypassingAction(
        Artifact input, Artifact output, AtomicInteger executionCounter) {
      super(input, output, executionCounter);
    }

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

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

  /** A mock skyframe-aware action that counts how many times it was executed. */
  private static class SkyframeAwareExecutionCountingAction
      extends ExecutionCountingCacheBypassingAction implements SkyframeAwareAction<IOException> {
    private final SkyKey actionDepKey;

    SkyframeAwareExecutionCountingAction(
        Artifact input, Artifact output, AtomicInteger executionCounter, SkyKey actionDepKey) {
      super(input, output, executionCounter);
      this.actionDepKey = actionDepKey;
    }

    @Override
    public Object processSkyframeValues(
        ImmutableList<? extends SkyKey> keys,
        SkyframeIterableResult values,
        boolean valuesMissing) {
      assertThat(keys).containsExactly(actionDepKey);
      return null;
    }

    @Override
    public ImmutableList<SkyKey> getDirectSkyframeDependencies() {
      return ImmutableList.of(actionDepKey);
    }

    @Override
    public Class<IOException> getExceptionType() {
      return IOException.class;
    }

    @Override
    public ImmutableGraph<SkyKey> getSkyframeDependenciesForRewinding(SkyKey self) {
      throw new UnsupportedOperationException();
    }
  }

  private interface ExecutionCountingActionFactory {
    ExecutionCountingAction create(Artifact input, Artifact output, AtomicInteger executionCounter);
  }

  private enum ChangeArtifact {
    DONT_CHANGE,
    CHANGE_MTIME {
      @Override
      boolean changeMtime() {
        return true;
      }
    },
    CHANGE_MTIME_AND_CONTENT {
      @Override
      boolean changeMtime() {
        return true;
      }

      @Override
      boolean changeContent() {
        return true;
      }
    };

    boolean changeMtime() {
      return false;
    }

    boolean changeContent() {
      return false;
    }
  }

  private enum ExpectActionIs {
    NOT_DIRTIED {
      @Override
      boolean actuallyClean() {
        return true;
      }
    },
    DIRTIED_BUT_VERIFIED_CLEAN {
      @Override
      boolean dirtied() {
        return true;
      }

      @Override
      boolean actuallyClean() {
        return true;
      }
    },

    // REBUILT_BUT_ACTION_CACHE_HIT,
    // This would be a bug, symptom of a skyframe-aware action that doesn't bypass the action cache
    // and is incorrectly regarded as an action cache hit when its inputs stayed the same but its
    // "skyframe dependencies" changed.

    REEXECUTED {
      @Override
      boolean dirtied() {
        return true;
      }

      @Override
      boolean reexecuted() {
        return true;
      }
    };

    boolean dirtied() {
      return false;
    }

    boolean actuallyClean() {
      return false;
    }

    boolean reexecuted() {
      return false;
    }
  }

  /** Ensure that a file's ctime was updated from an older value. */
  private static void checkCtimeUpdated(Path path, long oldCtime) throws IOException {
    if (oldCtime >= path.stat().getLastChangeTime()) {
      throw new IllegalStateException(String.format("path=(%s), ctime=(%d)", path, oldCtime));
    }
  }

  private void maybeChangeFile(Artifact file, ChangeArtifact changeRequest) throws Exception {
    if (changeRequest == ChangeArtifact.DONT_CHANGE) {
      return;
    }

    Path path = file.getPath();

    if (changeRequest.changeMtime()) {
      long ctime = path.stat().getLastChangeTime();
      // Ensure enough time elapsed for file updates to have a visible effect on the file's ctime.
      TimestampGranularityUtils.waitForTimestampGranularity(ctime, reporter.getOutErr());
      // waitForTimestampGranularity waits long enough for System.currentTimeMillis() to be greater
      // than the time at the setCommandStartTime() call. Therefore setting
      // System.currentTimeMillis() is guaranteed to advance the file's ctime.
      path.setLastModifiedTime(System.currentTimeMillis());
      checkCtimeUpdated(path, ctime);
    }

    if (changeRequest.changeContent()) {
      long ctime = path.stat().getLastChangeTime();
      // Ensure enough time elapsed for file updates to have a visible effect on the file's ctime.
      TimestampGranularityUtils.waitForTimestampGranularity(ctime, reporter.getOutErr());
      appendToFile(path);
      checkCtimeUpdated(path, ctime);
    }

    // Invalidate the file state value to inform Skyframe that the file may have changed.
    // This will also invalidate the action execution value.
    differencer.invalidate(
        ImmutableList.of(
            FileStateValue.key(
                RootedPath.toRootedPath(file.getRoot().getRoot(), file.getRootRelativePath()))));
  }

  private void assertActionExecutions(
      ExecutionCountingActionFactory actionFactory,
      ChangeArtifact changeActionInput,
      Callable<Void> betweenBuilds,
      ExpectActionIs expectActionIs)
      throws Exception {
    // Set up the action's input, output, owner and most importantly the execution counter.
    Artifact actionInput = createSourceArtifact("foo/action-input.txt");
    Artifact actionOutput = createDerivedArtifact("foo/action-output.txt");
    AtomicInteger executionCounter = new AtomicInteger(0);

    scratch.file(actionInput.getPath().getPathString(), "foo");

    // Generating actions of artifacts are found by looking them up in the graph. The lookup value
    // must be present in the graph before execution.
    Action action = actionFactory.create(actionInput, actionOutput, executionCounter);
    registerAction(action);

    // Build the output for the first time.
    builder.buildArtifacts(
        reporter,
        ImmutableSet.of(actionOutput),
        null,
        null,
        null,
        null,
        null,
        executor,
        null,
        null,
        options,
        null,
        null,
        /* trustRemoteArtifacts= */ false);

    // Check that our invalidation receiver is working correctly. We'll rely on it again.
    SkyKey actionKey = ActionLookupData.create(ACTION_LOOKUP_KEY, 0);
    TrackingEvaluationProgressReceiver.EvaluatedEntry evaluatedAction =
        progressReceiver.getEvalutedEntry(actionKey);
    assertThat(evaluatedAction).isNotNull();

    // Mutate the action input if requested.
    maybeChangeFile(actionInput, changeActionInput);

    // Execute user code before next build.
    betweenBuilds.call();

    // Rebuild the output.
    progressReceiver.reset();
    builder.buildArtifacts(
        reporter,
        ImmutableSet.of(actionOutput),
        null,
        null,
        null,
        null,
        null,
        executor,
        null,
        null,
        options,
        null,
        null,
        /* trustRemoteArtifacts= */ false);

    if (expectActionIs.dirtied()) {
      assertThat(progressReceiver.wasInvalidated(actionKey)).isTrue();

      TrackingEvaluationProgressReceiver.EvaluatedEntry newEntry =
          progressReceiver.getEvalutedEntry(actionKey);
      assertThat(newEntry).isNotNull();
      if (expectActionIs.actuallyClean()) {
        // Action was dirtied but verified clean.
        assertThat(newEntry.state).isEqualTo(EvaluationState.CLEAN);
      } else {
        // Action was dirtied and rebuilt. It was either reexecuted or was an action cache hit,
        // doesn't matter here.
        assertThat(newEntry.state).isEqualTo(EvaluationState.BUILT);
      }
    } else {
      // Action was not dirtied.
      assertThat(progressReceiver.wasInvalidated(actionKey)).isFalse();
    }

    // Assert that the action was executed the right number of times. Whether the action execution
    // function was called again is up for the test method to verify.
    assertThat(executionCounter.get()).isEqualTo(expectActionIs.reexecuted() ? 2 : 1);
  }

  private RootedPath createSkyframeDepOfAction() throws Exception {
    scratch.file(rootDirectory.getRelative("action.dep").getPathString(), "blah");
    return RootedPath.toRootedPath(Root.fromPath(rootDirectory), PathFragment.create("action.dep"));
  }

  private static void appendToFile(Path path) throws Exception {
    try (OutputStream stm = path.getOutputStream(/*append=*/ true)) {
      stm.write("blah".getBytes(StandardCharsets.UTF_8));
    }
  }

  @Test
  public void testCacheCheckingActionWithContentChangingInput() throws Exception {
    assertActionWithContentChangingInput(/* unconditionalExecution */ false);
  }

  @Test
  public void testCacheBypassingActionWithContentChangingInput() throws Exception {
    assertActionWithContentChangingInput(/* unconditionalExecution */ true);
  }

  private void assertActionWithContentChangingInput(final boolean unconditionalExecution)
      throws Exception {
    // Assert that a simple, non-skyframe-aware action is executed twice
    // if its input's content changes between builds.
    assertActionExecutions(
        new ExecutionCountingActionFactory() {
          @Override
          public ExecutionCountingAction create(
              Artifact input, Artifact output, AtomicInteger executionCounter) {
            return unconditionalExecution
                ? new ExecutionCountingCacheBypassingAction(input, output, executionCounter)
                : new ExecutionCountingAction(input, output, executionCounter);
          }
        },
        ChangeArtifact.CHANGE_MTIME_AND_CONTENT,
        Callables.<Void>returning(null),
        ExpectActionIs.REEXECUTED);
  }

  @Test
  public void testCacheCheckingActionWithMtimeChangingInput() throws Exception {
    assertActionWithMtimeChangingInput(/* unconditionalExecution */ false);
  }

  @Test
  public void testCacheBypassingActionWithMtimeChangingInput() throws Exception {
    assertActionWithMtimeChangingInput(/* unconditionalExecution */ true);
  }

  private void assertActionWithMtimeChangingInput(final boolean unconditionalExecution)
      throws Exception {
    // Assert that a simple, non-skyframe-aware action is executed only once
    // if its input's mtime changes but its contents stay the same between builds.
    assertActionExecutions(
        new ExecutionCountingActionFactory() {
          @Override
          public ExecutionCountingAction create(
              Artifact input, Artifact output, AtomicInteger executionCounter) {
            return unconditionalExecution
                ? new ExecutionCountingCacheBypassingAction(input, output, executionCounter)
                : new ExecutionCountingAction(input, output, executionCounter);
          }
        },
        ChangeArtifact.CHANGE_MTIME,
        Callables.<Void>returning(null),
        unconditionalExecution
            ? ExpectActionIs.REEXECUTED
            : ExpectActionIs.DIRTIED_BUT_VERIFIED_CLEAN);
  }

  @Test
  public void testCacheCheckingActionWithNonChangingInput() throws Exception {
    assertActionWithNonChangingInput(/* unconditionalExecution */ false);
  }

  @Test
  public void testCacheBypassingActionWithNonChangingInput() throws Exception {
    assertActionWithNonChangingInput(/* unconditionalExecution */ true);
  }

  private void assertActionWithNonChangingInput(final boolean unconditionalExecution)
      throws Exception {
    // Assert that a simple, non-skyframe-aware action is executed only once
    // if its input does not change at all between builds.
    assertActionExecutions(
        new ExecutionCountingActionFactory() {
          @Override
          public ExecutionCountingAction create(
              Artifact input, Artifact output, AtomicInteger executionCounter) {
            return unconditionalExecution
                ? new ExecutionCountingCacheBypassingAction(input, output, executionCounter)
                : new ExecutionCountingAction(input, output, executionCounter);
          }
        },
        ChangeArtifact.DONT_CHANGE,
        Callables.<Void>returning(null),
        ExpectActionIs.NOT_DIRTIED);
  }

  private void assertActionWithMaybeChangingInputAndChangingSkyframeDeps(
      ChangeArtifact changeInputFile) throws Exception {
    final RootedPath depPath = createSkyframeDepOfAction();
    final SkyKey skyframeDep = FileStateValue.key(depPath);

    // Assert that an action-cache-check-bypassing action is executed twice if its skyframe deps
    // change while its input does not. The skyframe dependency is established by making the action
    // skyframe-aware and updating the value between builds.
    assertActionExecutions(
        new ExecutionCountingActionFactory() {
          @Override
          public ExecutionCountingAction create(
              Artifact input, Artifact output, AtomicInteger executionCounter) {
            return new SkyframeAwareExecutionCountingAction(
                input, output, executionCounter, skyframeDep);
          }
        },
        changeInputFile,
        new Callable<Void>() {
          @Override
          public Void call() throws Exception {
            // Invalidate the dependency and change what its value will be in the next build. This
            // should enforce rebuilding of the action.
            appendToFile(depPath.asPath());
            differencer.invalidate(ImmutableList.of(skyframeDep));
            return null;
          }
        },
        ExpectActionIs.REEXECUTED);
  }

  @Test
  public void testActionWithNonChangingInputButChangingSkyframeDeps() throws Exception {
    assertActionWithMaybeChangingInputAndChangingSkyframeDeps(ChangeArtifact.DONT_CHANGE);
  }

  @Test
  public void testActionWithChangingInputMtimeAndChangingSkyframeDeps() throws Exception {
    assertActionWithMaybeChangingInputAndChangingSkyframeDeps(ChangeArtifact.CHANGE_MTIME);
  }

  @Test
  public void testActionWithChangingInputAndChangingSkyframeDeps() throws Exception {
    assertActionWithMaybeChangingInputAndChangingSkyframeDeps(
        ChangeArtifact.CHANGE_MTIME_AND_CONTENT);
  }

  @Test
  public void testActionWithNonChangingInputAndNonChangingSkyframeDeps() throws Exception {
    final SkyKey skyframeDep = FileStateValue.key(createSkyframeDepOfAction());

    // Assert that an action-cache-check-bypassing action is executed only once if neither its input
    // nor its Skyframe dependency changes between builds.
    assertActionExecutions(
        new ExecutionCountingActionFactory() {
          @Override
          public ExecutionCountingAction create(
              Artifact input, Artifact output, AtomicInteger executionCounter) {
            return new SkyframeAwareExecutionCountingAction(
                input, output, executionCounter, skyframeDep);
          }
        },
        ChangeArtifact.DONT_CHANGE,
        new Callable<Void>() {
          @Override
          public Void call() throws Exception {
            // Invalidate the dependency but leave its value up-to-date, so the action should not
            // be rebuilt.
            differencer.invalidate(ImmutableList.of(skyframeDep));
            return null;
          }
        },
        ExpectActionIs.DIRTIED_BUT_VERIFIED_CLEAN);
  }

  private abstract static class SingleOutputAction extends AbstractAction {
    SingleOutputAction(@Nullable Artifact input, Artifact output) {
      super(
          ActionsTestUtil.NULL_ACTION_OWNER,
          input == null
              ? NestedSetBuilder.emptySet(Order.STABLE_ORDER)
              : NestedSetBuilder.create(Order.STABLE_ORDER, input),
          ImmutableSet.of(output));
    }

    protected static final class Buffer {
      final int size;
      final byte[] data;

      Buffer(byte[] data, int size) {
        this.data = data;
        this.size = size;
      }
    }

    protected Buffer readInput() throws ActionExecutionException {
      byte[] input = new byte[100];
      int inputLen = 0;
      try (InputStream in = getPrimaryInput().getPath().getInputStream()) {
        inputLen = in.read(input, 0, input.length);
      } catch (IOException e) {
        throw new ActionExecutionException(
            e, this, false, CrashFailureDetails.detailedExitCodeForThrowable(e));
      }
      return new Buffer(input, inputLen);
    }

    protected void writeOutput(@Nullable Buffer buf, String data) throws ActionExecutionException {
      try (OutputStream out = getPrimaryOutput().getPath().getOutputStream()) {
        if (buf != null) {
          out.write(buf.data, 0, buf.size);
        }
        out.write(data.getBytes(StandardCharsets.UTF_8), 0, data.length());
      } catch (IOException e) {
        throw new ActionExecutionException(
            e, this, false, CrashFailureDetails.detailedExitCodeForThrowable(e));
      }
    }

    @Override
    public String getMnemonic() {
      return "MockActionMnemonic";
    }

    @Override
    protected void computeKey(
        ActionKeyContext actionKeyContext,
        @Nullable Artifact.ArtifactExpander artifactExpander,
        Fingerprint fp) {
      fp.addInt(42);
    }
  }

  private abstract static class SingleOutputSkyframeAwareAction extends SingleOutputAction
      implements SkyframeAwareAction<IOException> {
    SingleOutputSkyframeAwareAction(@Nullable Artifact input, Artifact output) {
      super(input, output);
    }

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

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

    @Override
    public Class<IOException> getExceptionType() {
      return IOException.class;
    }
  }

  /**
   * Regression test to avoid a potential race condition in {@link ActionExecutionFunction}.
   *
   * <p>The test ensures that when ActionExecutionFunction executes a Skyframe-aware action
   * (implementor of {@link SkyframeAwareAction}), ActionExecutionFunction first requests the inputs
   * of the action and ensures they are built before requesting any of its Skyframe dependencies.
   *
   * <p>This strict ordering is very important to avoid the race condition, which could arise if the
   * compute method were too eager to request all dependencies: request input files but even if some
   * are missing, request also the skyframe-dependencies. The race is described in this method's
   * body.
   */
  @Test
  public void testRaceConditionBetweenInputAcquisitionAndSkyframeDeps() throws Exception {
    // Sequence of events on threads A and B, showing SkyFunctions and requested SkyKeys, leading
    // to an InconsistentFilesystemException:
    //
    // _______________[Thread A]_________________|_______________[Thread B]_________________
    // ActionExecutionFunction(gen2_action:      | idle
    //   genfiles/gen1 -> genfiles/foo/bar/gen2) |
    // ARTIFACT:genfiles/gen1                    |
    // MOCK_VALUE:dummy_argument                 |
    // env.valuesMissing():yes ==> return        |
    //                                           |
    // ArtifactFunction(genfiles/gen1)           | MockFunction()
    // CONFIGURED_TARGET://foo:gen1              | FILE:genfiles/foo
    // ACTION_EXECUTION:gen1_action              | env.valuesMissing():yes ==> return
    // env.valuesMissing():yes ==> return        |
    //                                           | FileFunction(genfiles/foo)
    // ActionExecutionFunction(gen1_action)      | FILE:genfiles
    // ARTIFACT:genfiles/gen0                    | env.valuesMissing():yes ==> return
    // env.valuesMissing():yes ==> return        |
    //                                           | FileFunction(genfiles)
    // ArtifactFunction(genfiles/gen0)           | FILE_STATE:genfiles
    // CONFIGURED_TARGET://foo:gen0              | env.valuesMissing():yes ==> return
    // ACTION_EXECUTION:gen0_action              |
    // env.valuesMissing():yes ==> return        | FileStateFunction(genfiles)
    //                                           | stat genfiles
    // ActionExecutionFunction(gen0_action)      | return FileStateValue:non-existent
    // create output directory: genfiles         |
    // working                                   | FileFunction(genfiles/foo)
    //                                           | FILE:genfiles
    //                                           | FILE_STATE:genfiles/foo
    //                                           | env.valuesMissing():yes ==> return
    //                                           |
    //                                           | FileStateFunction(genfiles/foo)
    //                                           | stat genfiles/foo
    //                                           | return FileStateValue:non-existent
    //                                           |
    // done, created genfiles/gen0               | FileFunction(genfiles/foo)
    // return ActionExecutionValue(gen0_action)  | FILE:genfiles
    //                                           | FILE_STATE:genfiles/foo
    // ArtifactFunction(genfiles/gen0)           | return FileValue(genfiles/foo:non-existent)
    // CONFIGURED_TARGET://foo:gen0              |
    // ACTION_EXECUTION:gen0_action              | MockFunction()
    // return ArtifactSkyKey(genfiles/gen0)      | FILE:genfiles/foo
    //                                           | FILE:genfiles/foo/bar/gen1
    // ActionExecutionFunction(gen1_action)      | env.valuesMissing():yes ==> return
    // ARTIFACT:genfiles/gen0                    |
    // create output directory: genfiles/foo/bar | FileFunction(genfiles/foo/bar/gen1)
    // done, created genfiles/foo/bar/gen1       | FILE:genfiles/foo/bar
    // return ActionExecutionValue(gen1_action)  | env.valuesMissing():yes ==> return
    //                                           |
    // idle                                      | FileFunction(genfiles/foo/bar)
    //                                           | FILE:genfiles/foo
    //                                           | FILE_STATE:genfiles/foo/bar
    //                                           | env.valuesMissing():yes ==> return
    //                                           |
    //                                           | FileStateFunction(genfiles/foo/bar)
    //                                           | stat genfiles/foo/bar
    //                                           | return FileStateValue:directory
    //                                           |
    //                                           | FileFunction(genfiles/foo/bar)
    //                                           | FILE:genfiles/foo
    //                                           | FILE_STATE:genfiles/foo/bar
    //                                           | throw InconsistentFilesystemException:
    //                                           |     genfiles/foo doesn't exist but
    //                                           |     genfiles/foo/bar does!

    Artifact genFile1 = createDerivedArtifact("foo/bar/gen1.txt");
    Artifact genFile2 = createDerivedArtifact("gen2.txt");

    registerAction(
        new SingleOutputAction(null, genFile1) {
          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext)
              throws ActionExecutionException, InterruptedException {
            writeOutput(null, "gen1");
            return ActionResult.EMPTY;
          }
        });

    registerAction(
        new SingleOutputSkyframeAwareAction(genFile1, genFile2) {

          @Override
          public ImmutableList<SkyKey> getDirectSkyframeDependencies() {
            return ImmutableList.of();
          }

          @Override
          public Object processSkyframeValues(
              ImmutableList<? extends SkyKey> keys,
              SkyframeIterableResult values,
              boolean valuesMissing) {
            assertThat(keys).isEmpty();
            assertThat(valuesMissing).isFalse();
            return null;
          }

          @Override
          public ImmutableGraph<SkyKey> getSkyframeDependenciesForRewinding(SkyKey self) {
            throw new UnsupportedOperationException();
          }

          @Override
          public ActionResult execute(ActionExecutionContext actionExecutionContext)
              throws ActionExecutionException {
            writeOutput(readInput(), "gen2");
            return ActionResult.EMPTY;
          }
        });

    builder.buildArtifacts(
        reporter,
        ImmutableSet.of(genFile2),
        null,
        null,
        null,
        null,
        null,
        executor,
        null,
        null,
        options,
        null,
        null,
        /* trustRemoteArtifacts= */ false);
  }
}
