// 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.Iterables;
import com.google.common.collect.Sets;
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.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.testutil.TimestampGranularityUtils;
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.EvaluationProgressReceiver;
import com.google.devtools.build.skyframe.EvaluationProgressReceiver.EvaluationState;
import com.google.devtools.build.skyframe.SkyFunction.Environment;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
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);
  }

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

  private static final class TrackingEvaluationProgressReceiver
      extends EvaluationProgressReceiver.NullEvaluationProgressReceiver {

    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,
        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, ImmutableList.of(input), ImmutableList.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 = Iterables.getOnlyElement(getInputs()).getPath().getInputStream()) {
        inputLen = in.read(input);
      } catch (IOException e) {
        throw new ActionExecutionException(e, this, false);
      }

      // 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);
      }
      return ActionResult.EMPTY;
    }

    @Override
    public String getMnemonic() {
      return null;
    }

    @Override
    protected void computeKey(ActionKeyContext actionKeyContext, 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 {
    private final SkyKey actionDepKey;

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

    @Override
    public Object establishSkyframeDependencies(Environment env)
        throws ExceptionBase, InterruptedException {
      // Establish some Skyframe dependency. A real action would then use this to compute and
      // cache data for the execute(...) method.
      env.getValue(actionDepKey);
      return null;
    }

    @Override
    public ImmutableSet<SkyKey> getSkyframeDependenciesForRewinding() {
      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;
    }
  }

  /** Sanity check: ensure that a file's ctime was updated from an older value. */
  private 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());
      // Sanity check: ensure that updating the file's mtime indeed advanced its ctime.
      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);
      // Sanity check: ensure that appending to the file indeed advanced its ctime.
      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);

    // Sanity check that our invalidation receiver is working correctly. We'll rely on it again.
    SkyKey actionKey = ActionExecutionValue.key(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);

    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 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 ? ImmutableList.<Artifact>of() : ImmutableList.of(input),
          ImmutableList.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);
      }
      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);
      }
    }

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

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

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

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

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

  /**
   * 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 Object establishSkyframeDependencies(Environment env) throws ExceptionBase {
            assertThat(env.valuesMissing()).isFalse();
            return null;
          }

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

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

    builder.buildArtifacts(
        reporter,
        ImmutableSet.of(genFile2),
        null,
        null,
        null,
        null,
        null,
        executor,
        null,
        null,
        options,
        null,
        null);
  }
}
