// 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.base.Supplier;
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.Artifact;
import com.google.devtools.build.lib.actions.Executor;
import com.google.devtools.build.lib.actions.ResourceSet;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.actions.util.DummyExecutor;
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.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 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(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);
      }
    }

    public static final class EvaluatedEntry {
      public final SkyKey skyKey;
      public final SkyValue value;
      public final EvaluationState state;

      EvaluatedEntry(SkyKey skyKey, SkyValue value, EvaluationState state) {
        this.skyKey = skyKey;
        this.value = value;
        this.state = state;
      }

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

      @Override
      public int hashCode() {
        return Objects.hashCode(skyKey, value, 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 computed(SkyKey skyKey, long elapsedTimeNanos) {}

    @Override
    public void evaluated(
        SkyKey skyKey, Supplier<SkyValue> skyValueSupplier, EvaluationState state) {
      evaluated.add(new EvaluatedEntry(skyKey, skyValueSupplier.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 void 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);
      }
    }

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

    @Override
    protected String computeKey() {
      return getPrimaryOutput().getExecPathString() + executionCounter.get();
    }

    @Override
    public ResourceSet estimateResourceConsumption(Executor executor) {
      return ResourceSet.ZERO;
    }
  }

  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 void 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);
    }
  }

  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;
    }
  }

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

    if (changeRequest.changeMtime()) {
      // 1000000 should be larger than the filesystem timestamp granularity.
      file.getPath().setLastModifiedTime(file.getPath().getLastModifiedTime() + 1000000);
      tsgm.waitForTimestampGranularity(reporter.getOutErr());
    }

    if (changeRequest.changeContent()) {
      appendToFile(file.getPath());
    }

    // 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().getPath(), 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,
        executor,
        null,
        false,
        null,
        null);

    // Sanity check that our invalidation receiver is working correctly. We'll rely on it again.
    SkyKey actionKey = ActionExecutionValue.key(action);
    TrackingEvaluationProgressReceiver.EvaluatedEntry evaluatedAction =
        progressReceiver.getEvalutedEntry(actionKey);
    assertThat(evaluatedAction).isNotNull();
    SkyValue actionValue = evaluatedAction.value;

    // 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,
        executor,
        null,
        false,
        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);
        assertThat(newEntry.value).isEqualTo(actionValue);
      } 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);
        assertThat(newEntry.value).isNotEqualTo(actionValue);
      }
    } 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(rootDirectory, new PathFragment("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),
        ExpectActionIs.DIRTIED_BUT_VERIFIED_CLEAN);
  }

  public void testActionWithNonChangingInput(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 String computeKey() {
      return new Fingerprint().addInt(42).hexDigestAndReset();
    }

    @Override
    public ResourceSet estimateResourceConsumption(Executor executor) {
      return ResourceSet.ZERO;
    }
  }

  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 void execute(ActionExecutionContext actionExecutionContext)
              throws ActionExecutionException, InterruptedException {
            writeOutput(null, "gen1");
          }
        });

    registerAction(
        new SingleOutputSkyframeAwareAction(genFile1, genFile2) {
          @Override
          public void establishSkyframeDependencies(Environment env) throws ExceptionBase {
            assertThat(env.valuesMissing()).isFalse();
          }

          @Override
          public void execute(ActionExecutionContext actionExecutionContext)
              throws ActionExecutionException, InterruptedException {
            writeOutput(readInput(), "gen2");
          }
        });

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