// Copyright 2014 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.skyframe;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.common.truth.TruthJUnit.assume;
import static com.google.devtools.build.lib.testutil.EventIterableSubjectFactory.assertThatEvents;
import static com.google.devtools.build.skyframe.ErrorInfoSubjectFactory.assertThatErrorInfo;
import static com.google.devtools.build.skyframe.EvaluationResultSubjectFactory.assertThatEvaluationResult;
import static com.google.devtools.build.skyframe.GraphTester.CONCATENATE;
import static com.google.devtools.build.skyframe.GraphTester.COPY;
import static com.google.devtools.build.skyframe.GraphTester.NODE_TYPE;
import static com.google.devtools.build.skyframe.GraphTester.nonHermeticKey;
import static com.google.devtools.build.skyframe.GraphTester.skyKey;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import com.google.auto.value.AutoValue;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.eventbus.EventBus;
import com.google.common.testing.GcFinalization;
import com.google.common.util.concurrent.SettableFuture;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.devtools.build.lib.bugreport.BugReport;
import com.google.devtools.build.lib.events.DelegatingEventHandler;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventCollector;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.testutil.TestThread;
import com.google.devtools.build.lib.testutil.TestUtils;
import com.google.devtools.build.skyframe.Differencer.DiffWithDelta.Delta;
import com.google.devtools.build.skyframe.GraphTester.NotComparableStringValue;
import com.google.devtools.build.skyframe.GraphTester.StringValue;
import com.google.devtools.build.skyframe.GraphTester.TestFunction;
import com.google.devtools.build.skyframe.GraphTester.ValueComputer;
import com.google.devtools.build.skyframe.MemoizingEvaluator.GraphTransformerForTesting;
import com.google.devtools.build.skyframe.NodeEntry.DirtyType;
import com.google.devtools.build.skyframe.NotifyingHelper.EventType;
import com.google.devtools.build.skyframe.NotifyingHelper.Listener;
import com.google.devtools.build.skyframe.NotifyingHelper.Order;
import com.google.devtools.build.skyframe.QueryableGraph.Reason;
import com.google.devtools.build.skyframe.SkyFunction.Reset;
import com.google.devtools.build.skyframe.SkyFunctionException.Transience;
import com.google.devtools.build.skyframe.proto.GraphInconsistency.Inconsistency;
import com.google.errorprone.annotations.ForOverride;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;

/** Tests for a {@link MemoizingEvaluator}. */
public abstract class MemoizingEvaluatorTest {

  protected MemoizingEvaluatorTester tester;
  protected EventCollector eventCollector;
  protected ExtendedEventHandler reporter;
  protected EmittedEventState emittedEventState;

  // Knobs that control the size / duration of larger tests.
  private static final int TEST_NODE_COUNT = 100;
  private static final int TESTED_NODES = 10;
  private static final int RUNS = 10;

  @Before
  public void initializeTester() {
    initializeTester(null);
    initializeReporter();
  }

  private void initializeTester(@Nullable TrackingProgressReceiver customProgressReceiver) {
    emittedEventState = new EmittedEventState();
    tester = new MemoizingEvaluatorTester();
    if (customProgressReceiver != null) {
      tester.setProgressReceiver(customProgressReceiver);
    }
    tester.initialize();
  }

  protected TrackingProgressReceiver createTrackingProgressReceiver(
      boolean checkEvaluationResults) {
    return new TrackingProgressReceiver(checkEvaluationResults);
  }

  @After
  public void assertNoTrackedErrors() {
    TrackingAwaiter.INSTANCE.assertNoErrors();
  }

  protected RecordingDifferencer getRecordingDifferencer() {
    return new SequencedRecordingDifferencer();
  }

  @ForOverride
  protected abstract MemoizingEvaluator getMemoizingEvaluator(
      ImmutableMap<SkyFunctionName, SkyFunction> functions,
      Differencer differencer,
      EvaluationProgressReceiver progressReceiver,
      GraphInconsistencyReceiver graphInconsistencyReceiver,
      EventFilter eventFilter);

  /** Invoked immediately before each call to {@link MemoizingEvaluator#evaluate}. */
  @ForOverride
  protected void beforeEvaluation() {}

  /**
   * Invoked immediately after {@link MemoizingEvaluator#evaluate} with the {@link EvaluationResult}
   * or {@code null} if an exception was thrown.
   */
  @ForOverride
  protected void afterEvaluation(@Nullable EvaluationResult<?> result, EvaluationContext context)
      throws InterruptedException {}

  @ForOverride
  protected boolean cyclesDetected() {
    return true;
  }

  @ForOverride
  protected boolean resetSupported() {
    return true;
  }

  // TODO(jhorvitz): Skip irrelevant test cases if this is false.
  @ForOverride
  protected boolean incrementalitySupported() {
    return true;
  }

  private void initializeReporter() {
    eventCollector = new EventCollector();
    reporter = new Reporter(new EventBus(), eventCollector);
    tester.resetPlayedEvents();
  }

  @Test
  public void smoke() throws Exception {
    tester.set("x", new StringValue("y"));
    StringValue value = (StringValue) tester.evalAndGet("x");
    assertThat(value.getValue()).isEqualTo("y");
  }

  @Test
  public void evaluateEmptySet() throws InterruptedException {
    tester.eval(false, new SkyKey[0]);
    tester.eval(true, new SkyKey[0]);
  }

  @Test
  public void injectGraphTransformer_transformedGraphUsedForInMemoryGraph() {
    assume().that(tester.evaluator).isInstanceOf(AbstractInMemoryMemoizingEvaluator.class);
    InMemoryGraph realGraph = tester.evaluator.getInMemoryGraph();
    InMemoryGraph mockGraph = mock(InMemoryGraph.class);

    tester.evaluator.injectGraphTransformerForTesting(
        new GraphTransformerForTesting() {
          @Override
          public InMemoryGraph transform(InMemoryGraph graph) {
            assertThat(graph).isSameInstanceAs(realGraph);
            return mockGraph;
          }

          @Override
          public ProcessableGraph transform(ProcessableGraph graph) {
            throw new AssertionError(graph);
          }
        });

    assertThat(tester.evaluator.getInMemoryGraph()).isSameInstanceAs(mockGraph);
  }

  @Test
  public void injectGraphTransformer_transformedGraphUsedForEvaluation() throws Exception {
    Listener listener = mock(Listener.class);
    tester.evaluator.injectGraphTransformerForTesting(
        NotifyingHelper.makeNotifyingTransformer(listener));
    SkyKey key = skyKey("key");
    SkyValue val = new StringValue("val");
    tester.getOrCreate(key).setConstantValue(val);

    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(val);

    verify(listener).accept(key, EventType.GET_BATCH, Order.BEFORE, Reason.PRE_OR_POST_EVALUATION);
  }

  @Test
  public void injectGraphTransformer_multipleTransformersAppliedInOrder() throws Exception {
    Listener inner = mock(Listener.class);
    Listener outer = mock(Listener.class);
    tester.evaluator.injectGraphTransformerForTesting(
        NotifyingHelper.makeNotifyingTransformer(inner));
    tester.evaluator.injectGraphTransformerForTesting(
        NotifyingHelper.makeNotifyingTransformer(outer));
    SkyKey key = skyKey("key");
    SkyValue val = new StringValue("val");
    tester.getOrCreate(key).setConstantValue(val);

    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(val);

    InOrder inOrder = inOrder(inner, outer);
    inOrder.verify(outer).accept(key, EventType.SET_VALUE, Order.BEFORE, val);
    inOrder.verify(inner).accept(key, EventType.SET_VALUE, Order.BEFORE, val);
    inOrder.verify(inner).accept(key, EventType.SET_VALUE, Order.AFTER, val);
    inOrder.verify(outer).accept(key, EventType.SET_VALUE, Order.AFTER, val);
  }

  @Test
  public void invalidationWithNothingChanged() throws Exception {
    tester.set("x", new StringValue("y")).setWarning("fizzlepop");
    StringValue value = (StringValue) tester.evalAndGet("x");
    assertThat(value.getValue()).isEqualTo("y");
    assertThatEvents(eventCollector).containsExactly("fizzlepop");

    initializeReporter();
    tester.invalidate();
    value = (StringValue) tester.evalAndGet("x");
    assertThat(value.getValue()).isEqualTo("y");
  }

  @Test
  // Regression test for bug: "[skyframe-m1]: registerIfDone() crash".
  public void bubbleRace() throws Exception {
    // The top-level value declares dependencies on a "badValue" in error, and a "sleepyValue"
    // which is very slow. After "badValue" fails, the builder interrupts the "sleepyValue" and
    // attempts to re-run "top" for error bubbling. Make sure this doesn't cause a precondition
    // failure because "top" still has an outstanding dep ("sleepyValue").
    tester
        .getOrCreate("top")
        .setBuilder(
            (skyKey, env) -> {
              env.getValue(skyKey("sleepyValue"));
              try {
                env.getValueOrThrow(skyKey("badValue"), SomeErrorException.class);
              } catch (SomeErrorException e) {
                // In order to trigger this bug, we need to request a dep on an already computed
                // value.
                env.getValue(skyKey("otherValue1"));
              }
              if (!env.valuesMissing()) {
                throw new AssertionError("SleepyValue should always be unavailable");
              }
              return null;
            });
    tester
        .getOrCreate("sleepyValue")
        .setBuilder(
            (skyKey, env) -> {
              Thread.sleep(99999);
              throw new AssertionError("I should have been interrupted");
            });
    tester.getOrCreate("badValue").addDependency("otherValue1").setHasError(true);
    tester.getOrCreate("otherValue1").setConstantValue(new StringValue("otherVal1"));

    EvaluationResult<SkyValue> result = tester.eval(false, "top");
    assertThatEvaluationResult(result).hasSingletonErrorThat(skyKey("top"));
  }

  @Test
  public void testEnvProvidesTemporaryDirectDeps() throws Exception {
    AtomicInteger counter = new AtomicInteger();
    List<SkyKey> deps = Collections.synchronizedList(new ArrayList<>());
    SkyKey topKey = skyKey("top");
    SkyKey bottomKey = skyKey("bottom");
    SkyValue bottomValue = new StringValue("bottom");
    tester
        .getOrCreate(topKey)
        .setBuilder(
            (skyKey, env) -> {
              if (counter.getAndIncrement() > 0) {
                deps.addAll(env.getTemporaryDirectDeps().getDepGroup(0));
              } else {
                assertThat(env.getTemporaryDirectDeps().numGroups()).isEqualTo(0);
              }
              return env.getValue(bottomKey);
            });
    tester.getOrCreate(bottomKey).setConstantValue(bottomValue);
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ true, "top");
    assertThat(result.get(topKey)).isEqualTo(bottomValue);
    assertThat(deps).containsExactly(bottomKey);
  }

  @Test
  public void cachedErrorShutsDownThreadpool() throws Exception {
    // When a node throws an error on the first build,
    SkyKey cachedErrorKey = skyKey("error");
    tester.getOrCreate(cachedErrorKey).setHasError(true);
    assertThat(tester.evalAndGetError(/*keepGoing=*/ true, cachedErrorKey)).isNotNull();
    // And on the second build, it is requested as a dep,
    SkyKey topKey = skyKey("top");
    tester.getOrCreate(topKey).addDependency(cachedErrorKey).setComputedValue(CONCATENATE);
    // And another node throws an error, but waits to throw until the child error is thrown,
    SkyKey newErrorKey = skyKey("newError");
    tester
        .getOrCreate(newErrorKey)
        .setBuilder(
            new ChainedFunction.Builder()
                .setWaitForException(true)
                .setWaitToFinish(new CountDownLatch(0))
                .setValue(null)
                .build());
    // Then when evaluation happens,
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, newErrorKey, topKey);
    // The result has an error,
    assertThatEvaluationResult(result).hasError();
    // But the new error is not persisted to the graph, since the child error shut down evaluation.
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(newErrorKey).isNull();
  }

  @Test
  public void interruptBitCleared() {
    SkyKey interruptKey = skyKey("interrupt");
    tester.getOrCreate(interruptKey).setBuilder(INTERRUPT_BUILDER);
    assertThrows(
        InterruptedException.class, () -> tester.eval(/* keepGoing= */ true, interruptKey));
    assertThat(Thread.interrupted()).isFalse();
  }

  @Test
  public void crashAfterInterruptCrashes() {
    SkyKey failKey = skyKey("fail");
    SkyKey badInterruptkey = skyKey("bad-interrupt");
    // Given a SkyFunction implementation which is improperly coded to throw a runtime exception
    // when it is interrupted,
    CountDownLatch badInterruptStarted = new CountDownLatch(1);
    tester
        .getOrCreate(badInterruptkey)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) {
                badInterruptStarted.countDown();
                try {
                  Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
                  throw new AssertionError("Shouldn't have slept so long");
                } catch (InterruptedException e) {
                  throw new RuntimeException("I don't like being woken up!", e);
                }
              }
            });
    // And another SkyFunction that waits for the first to start, and then throws,
    tester
        .getOrCreate(failKey)
        .setBuilder(
            new ChainedFunction(
                null,
                badInterruptStarted,
                null,
                /*waitForException=*/ false,
                null,
                ImmutableList.of()));

    // When it is interrupted during evaluation (here, caused by the failure of the throwing
    // SkyFunction during a no-keep-going evaluation), then the ParallelEvaluator#evaluate call
    // throws a RuntimeException e where e.getCause() is the RuntimeException thrown by that
    // SkyFunction.
    RuntimeException e =
        assertThrows(
            RuntimeException.class,
            () -> tester.eval(/*keepGoing=*/ false, badInterruptkey, failKey));
    assertThat(e).hasCauseThat().hasMessageThat().isEqualTo("I don't like being woken up!");
  }

  @Test
  public void interruptAfterFailFails() throws Exception {
    SkyKey failKey = skyKey("fail");
    SkyKey interruptedKey = skyKey("interrupted");
    // Given a SkyFunction implementation that is properly coded to as not to throw a
    // runtime exception when it is interrupted,
    CountDownLatch interruptStarted = new CountDownLatch(1);
    tester
        .getOrCreate(interruptedKey)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                interruptStarted.countDown();
                Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
                throw new AssertionError("Shouldn't have slept so long");
              }
            });
    // And another SkyFunction that waits for the first to start, and then throws,
    tester
        .getOrCreate(failKey)
        .setBuilder(
            new ChainedFunction(
                null,
                interruptStarted,
                null,
                /*waitForException=*/ false,
                null,
                ImmutableList.of()));

    // When it is interrupted during evaluation (here, caused by the failure of a sibling node
    // during a no-keep-going evaluation),
    EvaluationResult<StringValue> result =
        tester.eval(/*keepGoing=*/ false, interruptedKey, failKey);
    // Then the ParallelEvaluator#evaluate call returns an EvaluationResult that has no error for
    // the interrupted SkyFunction.
    assertWithMessage(result.toString()).that(result.hasError()).isTrue();
    assertWithMessage(result.toString()).that(result.getError(failKey)).isNotNull();
    assertWithMessage(result.toString()).that(result.getError(interruptedKey)).isNull();
  }

  @Test
  public void deleteValues() throws Exception {
    tester
        .getOrCreate("top")
        .setComputedValue(CONCATENATE)
        .addDependency("d1")
        .addDependency("d2")
        .addDependency("d3");
    tester.set("d1", new StringValue("1"));
    StringValue d2 = new StringValue("2");
    tester.set("d2", d2);
    StringValue d3 = new StringValue("3");
    tester.set("d3", d3);
    tester.eval(true, "top");

    tester.delete("d1");
    tester.eval(true, "d3");

    assertThat(tester.getDirtyKeys()).isEmpty();
    assertThat(tester.getDeletedKeys()).isEqualTo(ImmutableSet.of(skyKey("d1"), skyKey("top")));
    assertThat(tester.getExistingValue("top")).isNull();
    assertThat(tester.getExistingValue("d1")).isNull();
    assertThat(tester.getExistingValue("d2")).isEqualTo(d2);
    assertThat(tester.getExistingValue("d3")).isEqualTo(d3);
  }

  @Test
  public void deleteOldNodesTest() throws Exception {
    SkyKey d2Key = nonHermeticKey("d2");
    tester
        .getOrCreate("top")
        .setComputedValue(CONCATENATE)
        .addDependency("d1")
        .addDependency(d2Key);
    tester.set("d1", new StringValue("one"));
    tester.set(d2Key, new StringValue("two"));
    tester.eval(true, "top");

    tester.set(d2Key, new StringValue("three"));
    tester.invalidate();
    tester.eval(true, d2Key);

    // The graph now contains the three above nodes (and ERROR_TRANSIENCE).
    assertThat(tester.evaluator.getValues().keySet())
        .containsExactly(skyKey("top"), skyKey("d1"), d2Key, ErrorTransienceValue.KEY);

    String[] noKeys = {};
    tester.evaluator.deleteDirty(2);
    tester.eval(true, noKeys);

    // The top node's value is dirty, but less than two generations old, so it wasn't deleted.
    assertThat(tester.evaluator.getValues().keySet())
        .containsExactly(skyKey("top"), skyKey("d1"), d2Key, ErrorTransienceValue.KEY);

    tester.evaluator.deleteDirty(2);
    tester.eval(true, noKeys);

    // The top node's value was dirty, and was two generations old, so it was deleted.
    assertThat(tester.evaluator.getValues().keySet())
        .containsExactly(skyKey("d1"), d2Key, ErrorTransienceValue.KEY);
  }

  @Test
  public void deleteDirtyCleanedValue() throws Exception {
    SkyKey leafKey = nonHermeticKey("leafKey");
    tester.getOrCreate(leafKey).setConstantValue(new StringValue("value"));
    SkyKey topKey = skyKey("topKey");
    tester.getOrCreate(topKey).addDependency(leafKey).setComputedValue(CONCATENATE);

    assertThat(tester.evalAndGet(/*keepGoing=*/ false, topKey)).isEqualTo(new StringValue("value"));
    failBuildAndRemoveValue(leafKey);
    tester.evaluator.deleteDirty(0);
  }

  @Test
  public void deleteNonexistentValues() throws Exception {
    tester.getOrCreate("d1").setConstantValue(new StringValue("1"));
    tester.delete("d1");
    tester.delete("d2");
    tester.eval(true, "d1");
  }

  @Test
  public void signalValueEnqueued() throws Exception {
    tester
        .getOrCreate("top1")
        .setComputedValue(CONCATENATE)
        .addDependency("d1")
        .addDependency("d2");
    tester.getOrCreate("top2").setComputedValue(CONCATENATE).addDependency("d3");
    tester.getOrCreate("top3");
    assertThat(tester.getEnqueuedValues()).isEmpty();

    tester.set("d1", new StringValue("1"));
    tester.set("d2", new StringValue("2"));
    tester.set("d3", new StringValue("3"));
    tester.eval(true, "top1");
    assertThat(tester.getEnqueuedValues())
        .containsExactlyElementsIn(MemoizingEvaluatorTester.toSkyKeys("top1", "d1", "d2"));

    tester.eval(true, "top2");
    assertThat(tester.getEnqueuedValues())
        .containsExactlyElementsIn(
            MemoizingEvaluatorTester.toSkyKeys("top1", "d1", "d2", "top2", "d3"));
  }

  @Test
  public void warningViaMultiplePaths() throws Exception {
    tester.set("d1", new StringValue("d1")).setWarning("warn-d1");
    tester.set("d2", new StringValue("d2")).setWarning("warn-d2");
    tester.getOrCreate("top").setComputedValue(CONCATENATE).addDependency("d1").addDependency("d2");
    initializeReporter();
    tester.evalAndGet("top");
    assertThatEvents(eventCollector).containsExactly("warn-d1", "warn-d2");
  }

  @Test
  public void warningBeforeErrorOnFailFastBuild() throws Exception {
    tester.set("dep", new StringValue("dep")).setWarning("warn-dep");
    SkyKey topKey = skyKey("top");
    tester.getOrCreate(topKey).setHasError(true).addDependency("dep");
    for (int i = 0; i < 2; i++) {
      initializeReporter();
      EvaluationResult<StringValue> result = tester.eval(false, "top");
      assertThatEvaluationResult(result)
          .hasSingletonErrorThat(topKey)
          .hasExceptionThat()
          .hasMessageThat()
          .isEqualTo(topKey.toString());
      assertThatEvaluationResult(result)
          .hasSingletonErrorThat(topKey)
          .hasExceptionThat()
          .isInstanceOf(SomeErrorException.class);
      if (i == 0) {
        assertThatEvents(eventCollector).containsExactly("warn-dep");
      }
    }
  }

  @Test
  public void warningAndErrorOnFailFastBuild() throws Exception {
    SkyKey topKey = skyKey("top");
    tester.set(topKey, new StringValue("top")).setWarning("warning msg").setHasError(true);
    for (int i = 0; i < 2; i++) {
      initializeReporter();
      EvaluationResult<StringValue> result = tester.eval(false, "top");
      assertThatEvaluationResult(result)
          .hasSingletonErrorThat(topKey)
          .hasExceptionThat()
          .hasMessageThat()
          .isEqualTo(topKey.toString());
      assertThatEvaluationResult(result)
          .hasSingletonErrorThat(topKey)
          .hasExceptionThat()
          .isInstanceOf(SomeErrorException.class);
      if (i == 0) {
        assertThatEvents(eventCollector).containsExactly("warning msg");
      }
    }
  }

  @Test
  public void warningAndErrorOnFailFastBuildAfterKeepGoingBuild() throws Exception {
    SkyKey topKey = skyKey("top");
    tester.set(topKey, new StringValue("top")).setWarning("warning msg").setHasError(true);
    for (int i = 0; i < 2; i++) {
      initializeReporter();
      EvaluationResult<StringValue> result = tester.eval(i == 0, "top");
      assertThatEvaluationResult(result)
          .hasSingletonErrorThat(topKey)
          .hasExceptionThat()
          .hasMessageThat()
          .isEqualTo(topKey.toString());
      assertThatEvaluationResult(result)
          .hasSingletonErrorThat(topKey)
          .hasExceptionThat()
          .isInstanceOf(SomeErrorException.class);
      if (i == 0) {
        assertThatEvents(eventCollector).containsExactly("warning msg");
      }
    }
  }

  @Test
  public void twoTLTsOnOneWarningValue() throws Exception {
    tester.set("t1", new StringValue("t1")).addDependency("dep");
    tester.set("t2", new StringValue("t2")).addDependency("dep");
    tester.set("dep", new StringValue("dep")).setWarning("look both ways before crossing");
    initializeReporter();
    tester.eval(/* keepGoing= */ false, "t1", "t2");
    assertThatEvents(eventCollector).containsExactly("look both ways before crossing");
  }

  @Test
  public void errorValueDepOnWarningValue() throws Exception {
    tester.getOrCreate("error-value").setHasError(true).addDependency("warning-value");
    tester
        .set("warning-value", new StringValue("warning-value"))
        .setWarning("don't chew with your mouth open");

    initializeReporter();
    tester.evalAndGetError(/* keepGoing= */ true, "error-value");
    assertThatEvents(eventCollector).containsExactly("don't chew with your mouth open");
  }

  @Test
  public void progressMessageOnlyPrintedTheFirstTime() throws Exception {
    // Skyframe does not store progress messages. Here we only see the message on the first build.
    tester.set("x", new StringValue("y")).setProgress("just letting you know");

    StringValue value = (StringValue) tester.evalAndGet("x");
    assertThat(value.getValue()).isEqualTo("y");
    assertThatEvents(eventCollector).containsExactly("just letting you know");

    initializeReporter();
    value = (StringValue) tester.evalAndGet("x");
    assertThat(value.getValue()).isEqualTo("y");
    assertThatEvents(eventCollector).isEmpty();
  }

  @Test
  public void depMessageBeforeNodeMessageOrNodeValue() throws Exception {
    SkyKey top = skyKey("top");
    AtomicBoolean depWarningEmitted = new AtomicBoolean(false);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (key.equals(top) && type == EventType.SET_VALUE) {
            assertThat(depWarningEmitted.get()).isTrue();
          }
        },
        /*deterministic=*/ false);
    String depWarning = "dep warning";
    Event topWarning = Event.warn("top warning");
    reporter =
        new DelegatingEventHandler(reporter) {
          @Override
          public void handle(Event e) {
            if (e.getMessage().equals(depWarning)) {
              depWarningEmitted.set(true);
            }
            if (e.equals(topWarning)) {
              assertThat(depWarningEmitted.get()).isTrue();
            }
            super.handle(e);
          }
        };
    SkyKey leaf = skyKey("leaf");
    tester.getOrCreate(leaf).setWarning(depWarning).setConstantValue(new StringValue("leaf"));
    tester
        .getOrCreate(top)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                SkyValue depValue = env.getValue(leaf);
                if (depValue != null) {
                  // Default GraphTester implementation warns before requesting deps, which doesn't
                  // work
                  // for ordering assertions with memoizing evaluator subclsses that don't store
                  // events
                  // and instead just pass them through directly. By warning after the dep is done
                  // we
                  // avoid that issue.
                  env.getListener().handle(topWarning);
                }
                return depValue;
              }
            });
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, top);
    assertThatEvaluationResult(result).hasEntryThat(top).isEqualTo(new StringValue("leaf"));
    assertThatEvents(eventCollector).containsExactly(depWarning, topWarning.getMessage()).inOrder();
  }

  @Test
  public void invalidationWithChangeAndThenNothingChanged() throws Exception {
    SkyKey bKey = nonHermeticKey("b");
    tester.getOrCreate("a").addDependency(bKey).setComputedValue(COPY);
    tester.set(bKey, new StringValue("y"));
    StringValue original = (StringValue) tester.evalAndGet("a");
    assertThat(original.getValue()).isEqualTo("y");
    tester.set(bKey, new StringValue("z"));
    tester.invalidate();
    StringValue old = (StringValue) tester.evalAndGet("a");
    assertThat(old.getValue()).isEqualTo("z");
    tester.invalidate();
    StringValue current = (StringValue) tester.evalAndGet("a");
    assertThat(current).isEqualTo(old);
  }

  @Test
  public void noKeepGoingErrorAfterKeepGoingError() throws Exception {
    SkyKey topKey = nonHermeticKey("top");
    SkyKey errorKey = skyKey("error");
    tester.getOrCreate(errorKey).setHasError(true);
    tester.getOrCreate(topKey).addDependency(errorKey).setComputedValue(CONCATENATE);
    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ true, topKey);
    assertThatEvaluationResult(result).hasSingletonErrorThat(topKey);
    tester.getOrCreate(topKey, /* markAsModified= */ true);
    tester.invalidate();
    result = tester.eval(/* keepGoing= */ false, topKey);
    assertThatEvaluationResult(result).hasSingletonErrorThat(topKey);
  }

  @Test
  public void transientErrorValueInvalidation() throws Exception {
    // Verify that invalidating errors causes all transient error values to be rerun.
    tester
        .getOrCreate("error-value")
        .setHasTransientError(true)
        .setProgress("just letting you know");

    tester.evalAndGetError(/*keepGoing=*/ true, "error-value");
    assertThatEvents(eventCollector).containsExactly("just letting you know");

    // Change the progress message.
    tester
        .getOrCreate("error-value")
        .setHasTransientError(true)
        .setProgress("letting you know more");

    // Without invalidating errors, we shouldn't show the new progress message.
    for (int i = 0; i < 2; i++) {
      initializeReporter();
      tester.evalAndGetError(/*keepGoing=*/ true, "error-value");
      assertThatEvents(eventCollector).isEmpty();
    }

    // When invalidating errors, we should show the new progress message.
    initializeReporter();
    tester.invalidateTransientErrors();
    tester.evalAndGetError(/*keepGoing=*/ true, "error-value");
    assertThatEvents(eventCollector).containsExactly("letting you know more");
  }

  @Test
  public void transientPruning() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    tester.getOrCreate("top").setHasTransientError(true).addDependency(leaf);
    tester.set(leaf, new StringValue("leafy"));
    tester.evalAndGetError(/*keepGoing=*/ true, "top");
    tester.getOrCreate(leaf, /*markAsModified=*/ true);
    tester.invalidate();
    tester.evalAndGetError(/*keepGoing=*/ true, "top");
  }

  @Test
  public void simpleDependency() throws Exception {
    tester.getOrCreate("ab").addDependency("a").setComputedValue(COPY);
    tester.set("a", new StringValue("me"));
    StringValue value = (StringValue) tester.evalAndGet("ab");
    assertThat(value.getValue()).isEqualTo("me");
  }

  @Test
  public void incrementalSimpleDependency() throws Exception {
    SkyKey aKey = nonHermeticKey("a");
    tester.getOrCreate("ab").addDependency(aKey).setComputedValue(COPY);
    tester.set(aKey, new StringValue("me"));
    tester.evalAndGet("ab");

    tester.set(aKey, new StringValue("other"));
    tester.invalidate();
    StringValue value = (StringValue) tester.evalAndGet("ab");
    assertThat(value.getValue()).isEqualTo("other");
  }

  @Test
  public void diamondDependency() throws Exception {
    SkyKey diamondBase = setupDiamondDependency();
    tester.set(diamondBase, new StringValue("me"));
    StringValue value = (StringValue) tester.evalAndGet("a");
    assertThat(value.getValue()).isEqualTo("meme");
  }

  @Test
  public void incrementalDiamondDependency() throws Exception {
    SkyKey diamondBase = setupDiamondDependency();
    tester.set(diamondBase, new StringValue("me"));
    tester.evalAndGet("a");

    tester.set(diamondBase, new StringValue("other"));
    tester.invalidate();
    StringValue value = (StringValue) tester.evalAndGet("a");
    assertThat(value.getValue()).isEqualTo("otherother");
  }

  private SkyKey setupDiamondDependency() {
    SkyKey diamondBase = nonHermeticKey("d");
    tester.getOrCreate("a").addDependency("b").addDependency("c").setComputedValue(CONCATENATE);
    tester.getOrCreate("b").addDependency(diamondBase).setComputedValue(COPY);
    tester.getOrCreate("c").addDependency(diamondBase).setComputedValue(COPY);
    return diamondBase;
  }

  // ParallelEvaluator notifies ValueProgressReceiver of already-built top-level values in error: we
  // built "top" and "mid" as top-level targets; "mid" contains an error. We make sure "mid" is
  // built as a dependency of "top" before enqueuing mid as a top-level target (by using a latch),
  // so that the top-level enqueuing finds that mid has already been built. The progress receiver
  // should be notified that mid has been built.
  @Test
  public void alreadyAnalyzedBadTarget() throws Exception {
    SkyKey mid = skyKey("zzmid");
    CountDownLatch valueSet = new CountDownLatch(1);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (!key.equals(mid)) {
            return;
          }
          switch (type) {
            case ADD_REVERSE_DEP:
              if (context == null) {
                // Context is null when we are enqueuing this value as a top-level job.
                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(valueSet, "value not set");
              }
              break;
            case SET_VALUE:
              valueSet.countDown();
              break;
            default:
              break;
          }
        },
        /* deterministic= */ true);
    SkyKey top = skyKey("aatop");
    tester.getOrCreate(top).addDependency(mid).setComputedValue(CONCATENATE);
    tester.getOrCreate(mid).setHasError(true);
    tester.eval(/* keepGoing= */ false, top, mid);
    assertThat(valueSet.getCount()).isEqualTo(0L);
    assertThat(tester.progressReceiver.evaluated).containsExactly(mid);
  }

  @Test
  public void receiverToldOfVerifiedValueDependingOnCycle() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey cycle = skyKey("cycle");
    SkyKey top = skyKey("top");
    tester.set(leaf, new StringValue("leaf"));
    tester.getOrCreate(cycle).addDependency(cycle);
    tester.getOrCreate(top).addDependency(leaf).addDependency(cycle);
    tester.eval(/* keepGoing= */ true, top);
    assertThat(tester.progressReceiver.evaluated).containsExactly(leaf, top, cycle);
    tester.progressReceiver.clear();
    tester.getOrCreate(leaf, /* markAsModified= */ true);
    tester.invalidate();
    tester.eval(/* keepGoing= */ true, top);
    assertThat(tester.progressReceiver.evaluated).containsExactly(leaf, top);
  }

  @Test
  public void incrementalAddedDependency() throws Exception {
    SkyKey aKey = nonHermeticKey("a");
    SkyKey bKey = nonHermeticKey("b");
    tester.getOrCreate(aKey).addDependency(bKey).setComputedValue(CONCATENATE);
    tester.set(bKey, new StringValue("first"));
    tester.set("c", new StringValue("second"));
    tester.evalAndGet(/* keepGoing= */ false, aKey);

    tester.getOrCreate(aKey).addDependency("c");
    tester.set(bKey, new StringValue("now"));
    tester.invalidate();
    StringValue value = (StringValue) tester.evalAndGet(/* keepGoing= */ false, aKey);
    assertThat(value.getValue()).isEqualTo("nowsecond");
  }

  @Test
  public void manyValuesDependOnSingleValue() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    String[] values = new String[TEST_NODE_COUNT];
    for (int i = 0; i < values.length; i++) {
      values[i] = Integer.toString(i);
      tester.getOrCreate(values[i]).addDependency(leaf).setComputedValue(COPY);
    }
    tester.set(leaf, new StringValue("leaf"));

    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ false, values);
    for (String value : values) {
      SkyValue actual = result.get(skyKey(value));
      assertThat(actual).isEqualTo(new StringValue("leaf"));
    }

    for (int j = 0; j < TESTED_NODES; j++) {
      tester.set(leaf, new StringValue("other" + j));
      tester.invalidate();
      result = tester.eval(/* keepGoing= */ false, values);
      for (int i = 0; i < values.length; i++) {
        SkyValue actual = result.get(skyKey(values[i]));
        assertWithMessage("Run " + j + ", value " + i)
            .that(actual)
            .isEqualTo(new StringValue("other" + j));
      }
    }
  }

  @Test
  public void singleValueDependsOnManyValues() throws Exception {
    SkyKey[] values = new SkyKey[TEST_NODE_COUNT];
    StringBuilder expected = new StringBuilder();
    for (int i = 0; i < values.length; i++) {
      String iString = Integer.toString(i);
      values[i] = nonHermeticKey(iString);
      tester.set(values[i], new StringValue(iString));
      expected.append(iString);
    }
    SkyKey rootKey = skyKey("root");
    TestFunction value = tester.getOrCreate(rootKey).setComputedValue(CONCATENATE);
    for (SkyKey skyKey : values) {
      value.addDependency(skyKey);
    }

    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ false, rootKey);
    assertThat(result.get(rootKey)).isEqualTo(new StringValue(expected.toString()));

    for (int j = 0; j < 10; j++) {
      expected.setLength(0);
      for (int i = 0; i < values.length; i++) {
        String s = "other" + i + " " + j;
        tester.set(values[i], new StringValue(s));
        expected.append(s);
      }
      tester.invalidate();

      result = tester.eval(/* keepGoing= */ false, rootKey);
      assertThat(result.get(rootKey)).isEqualTo(new StringValue(expected.toString()));
    }
  }

  @Test
  public void twoRailLeftRightDependencies() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    String[] leftValues = new String[TEST_NODE_COUNT];
    String[] rightValues = new String[TEST_NODE_COUNT];
    for (int i = 0; i < leftValues.length; i++) {
      leftValues[i] = "left-" + i;
      rightValues[i] = "right-" + i;
      if (i == 0) {
        tester.getOrCreate(leftValues[i]).addDependency(leaf).setComputedValue(COPY);
        tester.getOrCreate(rightValues[i]).addDependency(leaf).setComputedValue(COPY);
      } else {
        tester
            .getOrCreate(leftValues[i])
            .addDependency(leftValues[i - 1])
            .addDependency(rightValues[i - 1])
            .setComputedValue(new PassThroughSelected(skyKey(leftValues[i - 1])));
        tester
            .getOrCreate(rightValues[i])
            .addDependency(leftValues[i - 1])
            .addDependency(rightValues[i - 1])
            .setComputedValue(new PassThroughSelected(skyKey(rightValues[i - 1])));
      }
    }
    tester.set(leaf, new StringValue("leaf"));

    String lastLeft = "left-" + (TEST_NODE_COUNT - 1);
    String lastRight = "right-" + (TEST_NODE_COUNT - 1);

    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ false, lastLeft, lastRight);
    assertThat(result.get(skyKey(lastLeft))).isEqualTo(new StringValue("leaf"));
    assertThat(result.get(skyKey(lastRight))).isEqualTo(new StringValue("leaf"));

    for (int j = 0; j < TESTED_NODES; j++) {
      String value = "other" + j;
      tester.set(leaf, new StringValue(value));
      tester.invalidate();
      result = tester.eval(/* keepGoing= */ false, lastLeft, lastRight);
      assertThat(result.get(skyKey(lastLeft))).isEqualTo(new StringValue(value));
      assertThat(result.get(skyKey(lastRight))).isEqualTo(new StringValue(value));
    }
  }

  @Test
  public void noKeepGoingAfterKeepGoingCycle() throws Exception {
    initializeTester();
    SkyKey aKey = skyKey("a");
    SkyKey bKey = skyKey("b");
    SkyKey topKey = skyKey("top");
    SkyKey midKey = skyKey("mid");
    SkyKey goodKey = skyKey("good");
    StringValue goodValue = new StringValue("good");
    tester.set(goodKey, goodValue);
    tester.getOrCreate(topKey).addDependency(midKey);
    tester.getOrCreate(midKey).addDependency(aKey);
    tester.getOrCreate(aKey).addDependency(bKey);
    tester.getOrCreate(bKey).addDependency(aKey);
    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ true, topKey, goodKey);
    assertThat(result.get(goodKey)).isEqualTo(goodValue);
    assertThat(result.get(topKey)).isNull();
    ErrorInfo errorInfo = result.getError(topKey);
    CycleInfo cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo());
    if (cyclesDetected()) {
      assertThat(cycleInfo.getCycle()).containsExactly(aKey, bKey).inOrder();
      assertThat(cycleInfo.getPathToCycle()).containsExactly(topKey, midKey).inOrder();
    }

    tester.invalidate();
    result = tester.eval(/*keepGoing=*/ false, topKey, goodKey);
    assertThat(result.get(topKey)).isNull();
    errorInfo = result.getError(topKey);
    cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo());
    if (cyclesDetected()) {
      assertThat(cycleInfo.getCycle()).containsExactly(aKey, bKey).inOrder();
      assertThat(cycleInfo.getPathToCycle()).containsExactly(topKey, midKey).inOrder();
    }
  }

  @Test
  public void keepGoingCycleAlreadyPresent() throws Exception {
    SkyKey selfEdge = skyKey("selfEdge");
    tester.getOrCreate(selfEdge).addDependency(selfEdge).setComputedValue(CONCATENATE);
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ true, selfEdge);
    assertThatEvaluationResult(result).hasError();
    CycleInfo cycleInfo = Iterables.getOnlyElement(result.getError(selfEdge).getCycleInfo());
    if (cyclesDetected()) {
      CycleInfoSubjectFactory.assertThat(cycleInfo).hasCycleThat().containsExactly(selfEdge);
      CycleInfoSubjectFactory.assertThat(cycleInfo).hasPathToCycleThat().isEmpty();
    }
    SkyKey parent = skyKey("parent");
    tester.getOrCreate(parent).addDependency(selfEdge).setComputedValue(CONCATENATE);
    EvaluationResult<StringValue> result2 = tester.eval(/*keepGoing=*/ true, parent);
    assertThatEvaluationResult(result).hasError();
    CycleInfo cycleInfo2 = Iterables.getOnlyElement(result2.getError(parent).getCycleInfo());
    if (cyclesDetected()) {
      CycleInfoSubjectFactory.assertThat(cycleInfo2).hasCycleThat().containsExactly(selfEdge);
      CycleInfoSubjectFactory.assertThat(cycleInfo2).hasPathToCycleThat().containsExactly(parent);
    }
  }

  private void changeCycle(boolean keepGoing) throws Exception {
    SkyKey aKey = skyKey("a");
    SkyKey bKey = nonHermeticKey("b");
    SkyKey topKey = skyKey("top");
    SkyKey midKey = skyKey("mid");
    tester.getOrCreate(topKey).addDependency(midKey).setComputedValue(COPY);
    tester.getOrCreate(midKey).addDependency(aKey).setComputedValue(COPY);
    tester.getOrCreate(aKey).addDependency(bKey).setComputedValue(COPY);
    tester.getOrCreate(bKey).addDependency(aKey);
    EvaluationResult<StringValue> result = tester.eval(keepGoing, topKey);
    assertThat(result.get(topKey)).isNull();
    ErrorInfo errorInfo = result.getError(topKey);
    CycleInfo cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo());
    if (cyclesDetected()) {
      assertThat(cycleInfo.getCycle()).containsExactly(aKey, bKey).inOrder();
      assertThat(cycleInfo.getPathToCycle()).containsExactly(topKey, midKey).inOrder();
    }

    tester.getOrCreate(bKey).removeDependency(aKey);
    tester.set(bKey, new StringValue("bValue"));
    tester.invalidate();
    result = tester.eval(keepGoing, topKey);
    assertThat(result.get(topKey)).isEqualTo(new StringValue("bValue"));
    assertThat(result.getError(topKey)).isNull();
  }

  @Test
  public void changeCycle_NoKeepGoing() throws Exception {
    changeCycle(false);
  }

  @Test
  public void changeCycle_KeepGoing() throws Exception {
    changeCycle(true);
  }

  /**
   * @see ParallelEvaluatorTest#cycleAboveIndependentCycle()
   */
  @Test
  public void cycleAboveIndependentCycle() throws Exception {
    makeGraphDeterministic();
    SkyKey aKey = skyKey("a");
    SkyKey bKey = skyKey("b");
    SkyKey cKey = nonHermeticKey("c");
    SkyKey leafKey = nonHermeticKey("leaf");
    // When aKey depends on leafKey and bKey,
    tester
        .getOrCreate(aKey)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                env.getValuesAndExceptions(ImmutableList.of(leafKey, bKey));
                return null;
              }
            });
    // And bKey depends on cKey,
    tester.getOrCreate(bKey).addDependency(cKey);
    // And cKey depends on aKey and bKey in that order,
    tester.getOrCreate(cKey).addDependency(aKey).addDependency(bKey);
    // And leafKey is a leaf node,
    tester.set(leafKey, new StringValue("leafy"));
    // Then when we evaluate,
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ true, aKey);
    // aKey has an error,
    assertThat(result.get(aKey)).isNull();
    if (cyclesDetected()) {
      // And both cycles were found underneath aKey: the (aKey->bKey->cKey) cycle, and the
      // aKey->(bKey->cKey) cycle. This is because cKey depended on aKey and then bKey, so it pushed
      // them down on the stack in that order, so bKey was processed first. It found its cycle, then
      // popped off the stack, and then aKey was processed and found its cycle.
      assertThatEvaluationResult(result)
          .hasErrorEntryForKeyThat(aKey)
          .hasCycleInfoThat()
          .containsExactly(
              new CycleInfo(ImmutableList.of(aKey, bKey, cKey)),
              new CycleInfo(ImmutableList.of(aKey), ImmutableList.of(bKey, cKey)));
    } else {
      assertThatEvaluationResult(result)
          .hasErrorEntryForKeyThat(aKey)
          .hasCycleInfoThat()
          .hasSize(1);
    }
    // When leafKey is changed, so that aKey will be marked as NEEDS_REBUILDING,
    tester.set(leafKey, new StringValue("crunchy"));
    // And cKey is invalidated, so that cycle checking will have to explore the full graph,
    tester.getOrCreate(cKey, /*markAsModified=*/ true);
    tester.invalidate();
    // Then when we evaluate,
    EvaluationResult<StringValue> result2 = tester.eval(/*keepGoing=*/ true, aKey);
    // Things are just as before.
    assertThat(result2.get(aKey)).isNull();
    if (cyclesDetected()) {
      assertThatEvaluationResult(result)
          .hasErrorEntryForKeyThat(aKey)
          .hasCycleInfoThat()
          .containsExactly(
              new CycleInfo(ImmutableList.of(aKey, bKey, cKey)),
              new CycleInfo(ImmutableList.of(aKey), ImmutableList.of(bKey, cKey)));
    } else {
      assertThatEvaluationResult(result)
          .hasErrorEntryForKeyThat(aKey)
          .hasCycleInfoThat()
          .hasSize(1);
    }
  }

  /** Regression test: "crash in cycle checker with dirty values". */
  @Test
  public void cycleAndSelfEdgeWithDirtyValue() throws Exception {
    initializeTester();
    // The cycle detection algorithm non-deterministically traverses into children nodes, so
    // use explicit determinism.
    makeGraphDeterministic();
    SkyKey cycleKey1 = nonHermeticKey("ZcycleKey1");
    SkyKey cycleKey2 = skyKey("AcycleKey2");
    tester
        .getOrCreate(cycleKey1)
        .addDependency(cycleKey2)
        .addDependency(cycleKey1)
        .setComputedValue(CONCATENATE);
    tester.getOrCreate(cycleKey2).addDependency(cycleKey1).setComputedValue(COPY);
    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ true, cycleKey1);
    assertThat(result.get(cycleKey1)).isNull();
    ErrorInfo errorInfo = result.getError(cycleKey1);
    CycleInfo cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo());
    if (cyclesDetected()) {
      assertThat(cycleInfo.getCycle()).containsExactly(cycleKey1).inOrder();
      assertThat(cycleInfo.getPathToCycle()).isEmpty();
    }
    tester.getOrCreate(cycleKey1, /*markAsModified=*/ true);
    tester.invalidate();
    result = tester.eval(/*keepGoing=*/ true, cycleKey1, cycleKey2);
    assertThat(result.get(cycleKey1)).isNull();
    errorInfo = result.getError(cycleKey1);
    cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo());
    if (cyclesDetected()) {
      assertThat(cycleInfo.getCycle()).containsExactly(cycleKey1).inOrder();
      assertThat(cycleInfo.getPathToCycle()).isEmpty();
    }
    cycleInfo =
        Iterables.getOnlyElement(
            tester.evaluator.getExistingErrorForTesting(cycleKey2).getCycleInfo());
    if (cyclesDetected()) {
      assertThat(cycleInfo.getCycle()).containsExactly(cycleKey1).inOrder();
      assertThat(cycleInfo.getPathToCycle()).containsExactly(cycleKey2).inOrder();
    }
  }

  @Test
  public void cycleAndSelfEdgeWithDirtyValueInSameGroup() throws Exception {
    makeGraphDeterministic();
    SkyKey cycleKey1 = skyKey("ZcycleKey1");
    SkyKey cycleKey2 = skyKey("AcycleKey2");
    tester.getOrCreate(cycleKey2).addDependency(cycleKey2).setComputedValue(CONCATENATE);
    tester
        .getOrCreate(cycleKey1)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                // The order here is important -- 2 before 1.
                SkyframeLookupResult result =
                    env.getValuesAndExceptions(ImmutableList.of(cycleKey2, cycleKey1));
                Preconditions.checkState(env.valuesMissing(), result);
                return null;
              }
            });
    // Evaluate twice to make sure nothing strange happens with invalidation the second time.
    for (int i = 0; i < 2; i++) {
      EvaluationResult<SkyValue> result = tester.eval(/*keepGoing=*/ true, cycleKey1);
      assertThat(result.get(cycleKey1)).isNull();
      ErrorInfo errorInfo = result.getError(cycleKey1);
      CycleInfo cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo());
      if (cyclesDetected()) {
        assertThat(cycleInfo.getCycle()).containsExactly(cycleKey1).inOrder();
        assertThat(cycleInfo.getPathToCycle()).isEmpty();
      }
    }
  }

  /** Regression test: "crash in cycle checker with dirty values". */
  @Test
  public void cycleWithDirtyValue() throws Exception {
    SkyKey cycleKey1 = nonHermeticKey("cycleKey1");
    SkyKey cycleKey2 = skyKey("cycleKey2");
    tester.getOrCreate(cycleKey1).addDependency(cycleKey2).setComputedValue(COPY);
    tester.getOrCreate(cycleKey2).addDependency(cycleKey1).setComputedValue(COPY);
    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ true, cycleKey1);
    assertThat(result.get(cycleKey1)).isNull();
    ErrorInfo errorInfo = result.getError(cycleKey1);
    CycleInfo cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo());
    if (cyclesDetected()) {
      assertThat(cycleInfo.getCycle()).containsExactly(cycleKey1, cycleKey2).inOrder();
      assertThat(cycleInfo.getPathToCycle()).isEmpty();
    }
    tester.getOrCreate(cycleKey1, /*markAsModified=*/ true);
    tester.invalidate();
    result = tester.eval(/*keepGoing=*/ true, cycleKey1);
    assertThat(result.get(cycleKey1)).isNull();
    errorInfo = result.getError(cycleKey1);
    cycleInfo = Iterables.getOnlyElement(errorInfo.getCycleInfo());
    if (cyclesDetected()) {
      assertThat(cycleInfo.getCycle()).containsExactly(cycleKey1, cycleKey2).inOrder();
      assertThat(cycleInfo.getPathToCycle()).isEmpty();
    }
  }

  /**
   * {@link ParallelEvaluator} can be configured to not store errors alongside recovered values.
   *
   * @param errorsStoredAlongsideValues true if we expect Skyframe to store the error for the cycle
   *     in ErrorInfo. If true, supportsTransientExceptions must be true as well.
   * @param supportsTransientExceptions true if we expect Skyframe to mark an ErrorInfo as transient
   *     for certain exception types.
   * @param useTransientError true if the test should set the {@link TestFunction} it creates to
   *     throw a transient error.
   */
  protected void parentOfCycleAndErrorInternal(
      boolean errorsStoredAlongsideValues,
      boolean supportsTransientExceptions,
      boolean useTransientError)
      throws Exception {
    initializeTester();
    if (errorsStoredAlongsideValues) {
      Preconditions.checkArgument(supportsTransientExceptions);
    }
    SkyKey cycleKey1 = skyKey("cycleKey1");
    SkyKey cycleKey2 = skyKey("cycleKey2");
    SkyKey mid = skyKey("mid");
    SkyKey errorKey = skyKey("errorKey");
    tester.getOrCreate(cycleKey1).addDependency(cycleKey2).setComputedValue(COPY);
    tester.getOrCreate(cycleKey2).addDependency(cycleKey1).setComputedValue(COPY);
    TestFunction errorFunction = tester.getOrCreate(errorKey);
    if (useTransientError) {
      errorFunction.setHasTransientError(true);
    } else {
      errorFunction.setHasError(true);
    }
    tester
        .getOrCreate(mid)
        .addErrorDependency(errorKey, new StringValue("recovered"))
        .setComputedValue(COPY);
    SkyKey top = skyKey("top");
    CountDownLatch topEvaluated = new CountDownLatch(2);
    tester
        .getOrCreate(top)
        .setBuilder(
            new ChainedFunction(
                topEvaluated,
                null,
                null,
                false,
                new StringValue("unused"),
                ImmutableList.of(mid, cycleKey1)));
    EvaluationResult<StringValue> evalResult = tester.eval(true, top);
    assertThatEvaluationResult(evalResult).hasError();
    ErrorInfo errorInfo = evalResult.getError(top);
    assertThat(topEvaluated.getCount()).isEqualTo(1);
    if (errorsStoredAlongsideValues) {
      if (useTransientError) {
        // The parent should be transitively transient, since it transitively depends on a transient
        // error.
        assertThat(errorInfo.isTransitivelyTransient()).isTrue();
      } else {
        assertThatErrorInfo(errorInfo).isNotTransient();
      }
      assertThat(errorInfo.getException())
          .hasMessageThat()
          .isEqualTo(NODE_TYPE.getName() + ":errorKey");
    } else {
      // When errors are not stored alongside values, transient errors that are recovered from do
      // not make the parent transient
      if (supportsTransientExceptions) {
        assertThatErrorInfo(errorInfo).isTransient();
        assertThatErrorInfo(errorInfo).hasExceptionThat().isNotNull();
      } else {
        assertThatErrorInfo(errorInfo).isNotTransient();
        assertThatErrorInfo(errorInfo).hasExceptionThat().isNull();
      }
    }
    if (cyclesDetected()) {
      assertThatErrorInfo(errorInfo)
          .hasCycleInfoThat()
          .containsExactly(
              new CycleInfo(ImmutableList.of(top), ImmutableList.of(cycleKey1, cycleKey2)));
    } else {
      assertThatErrorInfo(errorInfo).hasCycleInfoThat().hasSize(1);
    }
    // But the parent itself shouldn't have a direct dep on the special error transience node.
    assertThatEvaluationResult(evalResult)
        .hasDirectDepsInGraphThat(top)
        .doesNotContain(ErrorTransienceValue.KEY);
  }

  @Test
  public void parentOfCycleAndError() throws Exception {
    parentOfCycleAndErrorInternal(
        /*errorsStoredAlongsideValues=*/ true,
        /*supportsTransientExceptions=*/ true,
        /*useTransientError=*/ true);
  }

  /**
   * Regression test: IllegalStateException in BuildingState.isReady(). The ParallelEvaluator used
   * to assume during cycle-checking that all values had been built as fully as possible -- that
   * evaluation had not been interrupted. However, we also do cycle-checking in nokeep-going mode
   * when a value throws an error (possibly prematurely shutting down evaluation) but that error
   * then bubbles up into a cycle.
   *
   * <p>We want to achieve the following state: we are checking for a cycle; the value we examine
   * has not yet finished checking its children to see if they are dirty; but all children checked
   * so far have been unchanged. This value is "otherTop". We first build otherTop, then mark its
   * first child changed (without actually changing it), and then do a second build. On the second
   * build, we also build "top", which requests a cycle that depends on an error. We wait to signal
   * otherTop that its first child is done until the error throws and shuts down evaluation. The
   * error then bubbles up to the cycle, and so the bubbling is aborted. Finally, cycle checking
   * happens, and otherTop is examined, as desired.
   */
  @Test
  public void cycleAndErrorAndReady() throws Exception {
    // This value will not have finished building on the second build when the error is thrown.
    SkyKey otherTop = skyKey("otherTop");
    SkyKey errorKey = skyKey("error");
    // Is the graph state all set up and ready for the error to be thrown? The three values are
    // exceptionMarker, cycle2Key, and dep1 (via signaling otherTop).
    CountDownLatch valuesReady = new CountDownLatch(3);
    // Is evaluation being shut down? This is counted down by the exceptionMarker's builder, after
    // it has waited for the threadpool's exception latch to be released.
    CountDownLatch errorThrown = new CountDownLatch(1);
    // We don't do anything on the first build.
    AtomicBoolean secondBuild = new AtomicBoolean(false);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (!secondBuild.get()) {
            return;
          }
          if (key.equals(otherTop) && type == EventType.SIGNAL) {
            // otherTop is being signaled that dep1 is done. Tell the error value that it is ready,
            // then wait until the error is thrown, so that otherTop's builder is not re-entered.
            valuesReady.countDown();
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(errorThrown, "error not thrown");
          }
        },
        /* deterministic= */ true);
    SkyKey dep1 = nonHermeticKey("dep1");
    tester.set(dep1, new StringValue("dep1"));
    SkyKey dep2 = skyKey("dep2");
    tester.set(dep2, new StringValue("dep2"));
    // otherTop should request the deps one at a time, so that it can be in the CHECK_DEPENDENCIES
    // state even after one dep is re-evaluated.
    tester
        .getOrCreate(otherTop)
        .setBuilder(
            (skyKey, env) -> {
              env.getValue(dep1);
              if (env.valuesMissing()) {
                return null;
              }
              env.getValue(dep2);
              return env.valuesMissing() ? null : new StringValue("otherTop");
            });
    // Prime the graph with otherTop, so we can dirty it next build.
    assertThat(tester.evalAndGet(/* keepGoing= */ false, otherTop))
        .isEqualTo(new StringValue("otherTop"));
    // Mark dep1 changed, so otherTop will be dirty and request re-evaluation of dep1.
    tester.getOrCreate(dep1, /* markAsModified= */ true);
    SkyKey topKey = skyKey("top");
    // Note that since DeterministicHelper alphabetizes reverse deps, it is important that
    // "cycle2" comes before "top".
    SkyKey cycle1Key = skyKey("cycle1");
    SkyKey cycle2Key = skyKey("cycle2");
    tester.getOrCreate(topKey).addDependency(cycle1Key).setComputedValue(CONCATENATE);
    tester
        .getOrCreate(cycle1Key)
        .addDependency(errorKey)
        .addDependency(cycle2Key)
        .setComputedValue(CONCATENATE);
    tester
        .getOrCreate(errorKey)
        .setBuilder(
            new ChainedFunction(
                /* notifyStart= */ null,
                /* waitToFinish= */ valuesReady,
                /* notifyFinish= */ null,
                /* waitForException= */ false,
                /* value= */ null,
                ImmutableList.of()));
    // Make sure cycle2Key has declared its dependence on cycle1Key before error throws.
    tester
        .getOrCreate(cycle2Key)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ valuesReady,
                null,
                null,
                false,
                new StringValue("never returned"),
                ImmutableList.of(cycle1Key)));
    // Value that waits until an exception is thrown to finish building. We use it just to be
    // informed when the threadpool is shutting down.
    SkyKey exceptionMarker = skyKey("exceptionMarker");
    tester
        .getOrCreate(exceptionMarker)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ valuesReady,
                /*waitToFinish=*/ new CountDownLatch(0),
                /*notifyFinish=*/ errorThrown,
                /*waitForException=*/ true,
                new StringValue("exception marker"),
                ImmutableList.of()));
    tester.invalidate();
    secondBuild.set(true);
    // otherTop must be first, since we check top-level values for cycles in the order in which
    // they appear here.
    EvaluationResult<StringValue> result =
        tester.eval(/*keepGoing=*/ false, otherTop, topKey, exceptionMarker);
    Iterable<CycleInfo> cycleInfos = result.getError(topKey).getCycleInfo();
    assertWithMessage(result.toString()).that(cycleInfos).isNotEmpty();
    CycleInfo cycleInfo = Iterables.getOnlyElement(cycleInfos);
    if (cyclesDetected()) {
      assertThat(result.errorMap().keySet()).containsExactly(topKey);
      assertThat(cycleInfo.getPathToCycle()).containsExactly(topKey);
      assertThat(cycleInfo.getCycle()).containsExactly(cycle1Key, cycle2Key);
    }
  }

  @Test
  public void breakCycle() throws Exception {
    SkyKey aKey = nonHermeticKey("a");
    SkyKey bKey = nonHermeticKey("b");
    // When aKey and bKey depend on each other,
    tester.getOrCreate(aKey).addDependency(bKey);
    tester.getOrCreate(bKey).addDependency(aKey);
    // And they are evaluated,
    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ true, aKey, bKey);
    // Then the evaluation is in error,
    assertThatEvaluationResult(result).hasError();
    // And each node has the expected cycle.
    assertThatEvaluationResult(result)
        .hasErrorEntryForKeyThat(aKey)
        .hasCycleInfoThat()
        .isNotEmpty();
    CycleInfo aCycleInfo = Iterables.getOnlyElement(result.getError(aKey).getCycleInfo());
    if (cyclesDetected()) {
      assertThat(aCycleInfo.getCycle()).containsExactly(aKey, bKey).inOrder();
      assertThat(aCycleInfo.getPathToCycle()).isEmpty();
    }
    assertThatEvaluationResult(result)
        .hasErrorEntryForKeyThat(bKey)
        .hasCycleInfoThat()
        .isNotEmpty();
    CycleInfo bCycleInfo = Iterables.getOnlyElement(result.getError(bKey).getCycleInfo());
    if (cyclesDetected()) {
      assertThat(bCycleInfo.getCycle()).containsExactly(bKey, aKey).inOrder();
      assertThat(bCycleInfo.getPathToCycle()).isEmpty();
    }

    // When both dependencies are broken,
    tester.getOrCreate(bKey).removeDependency(aKey);
    tester.set(bKey, new StringValue("bValue"));
    tester.getOrCreate(aKey).removeDependency(bKey);
    tester.set(aKey, new StringValue("aValue"));
    tester.invalidate();
    // And the nodes are re-evaluated,
    result = tester.eval(/*keepGoing=*/ true, aKey, bKey);
    // Then evaluation is successful and the nodes have the expected values.
    assertThatEvaluationResult(result).hasEntryThat(aKey).isEqualTo(new StringValue("aValue"));
    assertThatEvaluationResult(result).hasEntryThat(bKey).isEqualTo(new StringValue("bValue"));
  }

  @Test
  public void nodeInvalidatedThenDoubleCycle() throws InterruptedException {
    makeGraphDeterministic();
    // When topKey depends on depKey, and both are top-level nodes in the graph,
    SkyKey topKey = nonHermeticKey("bKey");
    SkyKey depKey = nonHermeticKey("aKey");
    tester.getOrCreate(topKey).addDependency(depKey).setConstantValue(new StringValue("a"));
    tester.getOrCreate(depKey).setConstantValue(new StringValue("b"));
    // Then evaluation is as expected.
    EvaluationResult<StringValue> result1 = tester.eval(/* keepGoing= */ true, topKey, depKey);
    assertThatEvaluationResult(result1).hasEntryThat(topKey).isEqualTo(new StringValue("a"));
    assertThatEvaluationResult(result1).hasEntryThat(depKey).isEqualTo(new StringValue("b"));
    assertThatEvaluationResult(result1).hasNoError();
    // When both nodes acquire self-edges, with topKey still also depending on depKey, in the same
    // group,
    tester.getOrCreate(depKey, /* markAsModified= */ true).addDependency(depKey);
    tester
        .getOrCreate(topKey, /* markAsModified= */ true)
        .setConstantValue(null)
        .removeDependency(depKey)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                // Order depKey first - makeGraphDeterministic() only makes the batch maps returned
                // by the graph deterministic, not the order of temporary direct deps. This makes
                // the order of deps match (alphabetized by the string representation).
                env.getValuesAndExceptions(ImmutableList.of(depKey, topKey));
                assertThat(env.valuesMissing()).isTrue();
                return null;
              }
            });
    tester.invalidate();
    // Then evaluation is as expected -- topKey has removed its dep on depKey (since depKey was not
    // done when topKey found its cycle), and both topKey and depKey have cycles.
    EvaluationResult<StringValue> result2 = tester.eval(/*keepGoing=*/ true, topKey, depKey);
    if (cyclesDetected()) {
      assertThatEvaluationResult(result2)
          .hasErrorEntryForKeyThat(topKey)
          .hasCycleInfoThat()
          .containsExactly(new CycleInfo(ImmutableList.of(topKey)));
      assertThatEvaluationResult(result2).hasDirectDepsInGraphThat(topKey).containsExactly(topKey);
      assertThatEvaluationResult(result2)
          .hasErrorEntryForKeyThat(depKey)
          .hasCycleInfoThat()
          .containsExactly(new CycleInfo(ImmutableList.of(depKey)));
    } else {
      assertThatEvaluationResult(result2)
          .hasErrorEntryForKeyThat(topKey)
          .hasCycleInfoThat()
          .hasSize(1);
      assertThatEvaluationResult(result2)
          .hasErrorEntryForKeyThat(depKey)
          .hasCycleInfoThat()
          .hasSize(1);
    }
    // When the nodes return to their original, error-free state,
    tester
        .getOrCreate(topKey, /*markAsModified=*/ true)
        .setBuilder(null)
        .addDependency(depKey)
        .setConstantValue(new StringValue("a"));
    tester.getOrCreate(depKey, /*markAsModified=*/ true).removeDependency(depKey);
    tester.invalidate();
    // Then evaluation is as expected.
    EvaluationResult<StringValue> result3 = tester.eval(/*keepGoing=*/ true, topKey, depKey);
    assertThatEvaluationResult(result3).hasEntryThat(topKey).isEqualTo(new StringValue("a"));
    assertThatEvaluationResult(result3).hasEntryThat(depKey).isEqualTo(new StringValue("b"));
    assertThatEvaluationResult(result3).hasNoError();
  }

  @SuppressWarnings("PreferJavaTimeOverload")
  @Test
  public void limitEvaluatorThreads() throws Exception {
    initializeTester();

    int numKeys = 10;
    Object lock = new Object();
    AtomicInteger inProgressCount = new AtomicInteger();
    int[] maxValue = {0};

    SkyKey topLevel = skyKey("toplevel");
    TestFunction topLevelBuilder = tester.getOrCreate(topLevel);
    for (int i = 0; i < numKeys; i++) {
      topLevelBuilder.addDependency("subKey" + i);
      tester
          .getOrCreate("subKey" + i)
          .setComputedValue(
              (deps, env) -> {
                int val = inProgressCount.incrementAndGet();
                synchronized (lock) {
                  if (val > maxValue[0]) {
                    maxValue[0] = val;
                  }
                }
                Uninterruptibles.sleepUninterruptibly(5, TimeUnit.SECONDS);

                inProgressCount.decrementAndGet();
                return new StringValue("abc");
              });
    }
    topLevelBuilder.setConstantValue(new StringValue("xyz"));

    EvaluationResult<StringValue> result =
        tester.eval(/*keepGoing=*/ true, /*numThreads=*/ 5, topLevel);
    assertThat(result.hasError()).isFalse();
    assertThat(maxValue[0]).isEqualTo(5);
  }

  @Test
  public void nodeIsChangedWithoutBeingEvaluated() throws Exception {
    SkyKey buildFile = nonHermeticKey("buildfile");
    SkyKey top = skyKey("top");
    SkyKey dep = nonHermeticKey("dep");
    tester.set(buildFile, new StringValue("depend on dep"));
    StringValue depVal = new StringValue("this is dep");
    tester.set(dep, depVal);
    tester
        .getOrCreate(top)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env)
                  throws SkyFunctionException, InterruptedException {
                StringValue val = (StringValue) env.getValue(buildFile);
                if (env.valuesMissing()) {
                  return null;
                }
                if (val.getValue().equals("depend on dep")) {
                  StringValue result = (StringValue) env.getValue(dep);
                  return env.valuesMissing() ? null : result;
                }
                throw new GenericFunctionException(
                    new SomeErrorException("bork"), Transience.PERSISTENT);
              }
            });
    assertThat(tester.evalAndGet("top")).isEqualTo(depVal);
    StringValue newDepVal = new StringValue("this is new dep");
    tester.set(dep, newDepVal);
    tester.set(buildFile, new StringValue("don't depend on dep"));
    tester.invalidate();
    tester.eval(/*keepGoing=*/ false, top);
    tester.set(buildFile, new StringValue("depend on dep"));
    tester.invalidate();
    assertThat(tester.evalAndGet("top")).isEqualTo(newDepVal);
  }

  /**
   * Regression test: error on clearMaybeDirtyValue. We do an evaluation of topKey, which registers
   * dependencies on midKey and errorKey. midKey enqueues slowKey, and waits. errorKey throws an
   * error, which bubbles up to topKey. If topKey does not unregister its dependence on midKey, it
   * will have a dangling reference to midKey after unfinished values are cleaned from the graph.
   * Note that slowKey will wait until errorKey has thrown and the threadpool has caught the
   * exception before returning, so the Evaluator will already have stopped enqueuing new jobs, so
   * midKey is not evaluated.
   */
  @Test
  public void incompleteDirectDepsAreClearedBeforeInvalidation() throws Exception {
    CountDownLatch slowStart = new CountDownLatch(1);
    CountDownLatch errorFinish = new CountDownLatch(1);
    SkyKey errorKey = nonHermeticKey("error");
    tester
        .getOrCreate(errorKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ null,
                /*waitToFinish=*/ slowStart,
                /*notifyFinish=*/ errorFinish,
                /*waitForException=*/ false,
                /*value=*/ null,
                /*deps=*/ ImmutableList.of()));
    SkyKey slowKey = skyKey("slow");
    tester
        .getOrCreate(slowKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ slowStart,
                /*waitToFinish=*/ errorFinish,
                /*notifyFinish=*/ null,
                /*waitForException=*/ true,
                new StringValue("slow"),
                /*deps=*/ ImmutableList.of()));
    SkyKey midKey = skyKey("mid");
    tester.getOrCreate(midKey).addDependency(slowKey).setComputedValue(COPY);
    SkyKey topKey = skyKey("top");
    tester
        .getOrCreate(topKey)
        .addDependency(midKey)
        .addDependency(errorKey)
        .setComputedValue(CONCATENATE);
    // slowKey starts -> errorKey finishes, written to graph -> slowKey finishes & (Visitor aborts)
    // -> topKey builds.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, topKey);
    assertThatEvaluationResult(result).hasSingletonErrorThat(topKey);
    // Make sure midKey didn't finish building.
    assertThat(tester.getExistingValue(midKey)).isNull();
    // Give slowKey a nice ordinary builder.
    tester
        .getOrCreate(slowKey, /*markAsModified=*/ false)
        .setBuilder(null)
        .setConstantValue(new StringValue("slow"));
    // Put midKey into the graph. It won't have a reverse dependence on topKey.
    tester.evalAndGet(/*keepGoing=*/ false, midKey);
    tester.differencer.invalidate(ImmutableList.of(errorKey));
    // topKey should not access midKey as if it were already registered as a dependency.
    tester.eval(/*keepGoing=*/ false, topKey);
  }

  /**
   * Regression test: error on clearMaybeDirtyValue. Same as the previous test, but the second
   * evaluation is keepGoing, which should cause an access of the children of topKey.
   */
  @Test
  public void incompleteDirectDepsAreClearedBeforeKeepGoing() throws Exception {
    initializeTester();
    CountDownLatch slowStart = new CountDownLatch(1);
    CountDownLatch errorFinish = new CountDownLatch(1);
    SkyKey errorKey = skyKey("error");
    tester
        .getOrCreate(errorKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ null,
                /*waitToFinish=*/ slowStart,
                /*notifyFinish=*/ errorFinish,
                /*waitForException=*/ false,
                /*value=*/ null,
                /*deps=*/ ImmutableList.of()));
    SkyKey slowKey = skyKey("slow");
    tester
        .getOrCreate(slowKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ slowStart,
                /*waitToFinish=*/ errorFinish,
                /*notifyFinish=*/ null,
                /*waitForException=*/ true,
                new StringValue("slow"),
                /*deps=*/ ImmutableList.of()));
    SkyKey midKey = skyKey("mid");
    tester.getOrCreate(midKey).addDependency(slowKey).setComputedValue(COPY);
    SkyKey topKey = skyKey("top");
    tester
        .getOrCreate(topKey)
        .addDependency(midKey)
        .addDependency(errorKey)
        .setComputedValue(CONCATENATE);
    // slowKey starts -> errorKey finishes, written to graph -> slowKey finishes & (Visitor aborts)
    // -> topKey builds.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, topKey);
    assertThatEvaluationResult(result).hasSingletonErrorThat(topKey);
    // Make sure midKey didn't finish building.
    assertThat(tester.getExistingValue(midKey)).isNull();
    // Give slowKey a nice ordinary builder.
    tester
        .getOrCreate(slowKey, /*markAsModified=*/ false)
        .setBuilder(null)
        .setConstantValue(new StringValue("slow"));
    // Put midKey into the graph. It won't have a reverse dependence on topKey.
    tester.evalAndGet(/*keepGoing=*/ false, midKey);
    // topKey should not access midKey as if it were already registered as a dependency.
    // We don't invalidate errors, but because topKey wasn't actually written to the graph last
    // build, it should be rebuilt here.
    tester.eval(/*keepGoing=*/ true, topKey);
  }

  /**
   * Regression test: tests that pass before other build actions fail yield crash in non -k builds.
   */
  private void passThenFailToBuild(boolean successFirst) throws Exception {
    CountDownLatch blocker = new CountDownLatch(1);
    SkyKey successKey = skyKey("success");
    tester
        .getOrCreate(successKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ null,
                /*waitToFinish=*/ null,
                /*notifyFinish=*/ blocker,
                /*waitForException=*/ false,
                new StringValue("yippee"),
                /*deps=*/ ImmutableList.of()));
    SkyKey slowFailKey = skyKey("slow_then_fail");
    tester
        .getOrCreate(slowFailKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ null,
                /*waitToFinish=*/ blocker,
                /*notifyFinish=*/ null,
                /*waitForException=*/ false,
                /*value=*/ null,
                /*deps=*/ ImmutableList.of()));

    EvaluationResult<StringValue> result;
    if (successFirst) {
      result = tester.eval(/*keepGoing=*/ false, successKey, slowFailKey);
    } else {
      result = tester.eval(/*keepGoing=*/ false, slowFailKey, successKey);
    }
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(slowFailKey);
    assertThat(result.values()).containsExactly(new StringValue("yippee"));
  }

  @Test
  public void passThenFailToBuild() throws Exception {
    passThenFailToBuild(true);
  }

  @Test
  public void passThenFailToBuildAlternateOrder() throws Exception {
    passThenFailToBuild(false);
  }

  @Test
  public void incompleteDirectDepsForDirtyValue() throws Exception {
    SkyKey topKey = nonHermeticKey("top");
    tester.set(topKey, new StringValue("initial"));
    // Put topKey into graph so it will be dirtied on next run.
    assertThat(tester.evalAndGet(/*keepGoing=*/ false, topKey))
        .isEqualTo(new StringValue("initial"));
    CountDownLatch slowStart = new CountDownLatch(1);
    CountDownLatch errorFinish = new CountDownLatch(1);
    SkyKey errorKey = skyKey("error");
    tester
        .getOrCreate(errorKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ null,
                /*waitToFinish=*/ slowStart,
                /*notifyFinish=*/ errorFinish,
                /*waitForException=*/ false,
                /*value=*/ null,
                /*deps=*/ ImmutableList.of()));
    SkyKey slowKey = skyKey("slow");
    tester
        .getOrCreate(slowKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ slowStart,
                /*waitToFinish=*/ errorFinish,
                /*notifyFinish=*/ null,
                /*waitForException=*/ true,
                new StringValue("slow"),
                /*deps=*/ ImmutableList.of()));
    SkyKey midKey = skyKey("mid");
    tester.getOrCreate(midKey).addDependency(slowKey).setComputedValue(COPY);
    tester.set(topKey, null);
    tester
        .getOrCreate(topKey)
        .addDependency(midKey)
        .addDependency(errorKey)
        .setComputedValue(CONCATENATE);
    tester.invalidate();
    // slowKey starts -> errorKey finishes, written to graph -> slowKey finishes & (Visitor aborts)
    // -> topKey builds.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, topKey);
    assertThatEvaluationResult(result).hasSingletonErrorThat(topKey);
    // Make sure midKey didn't finish building.
    assertThat(tester.getExistingValue(midKey)).isNull();
    // Give slowKey a nice ordinary builder.
    tester
        .getOrCreate(slowKey, /*markAsModified=*/ false)
        .setBuilder(null)
        .setConstantValue(new StringValue("slow"));
    // Put midKey into the graph. It won't have a reverse dependence on topKey.
    tester.evalAndGet(/*keepGoing=*/ false, midKey);
    // topKey should not access midKey as if it were already registered as a dependency.
    // We don't invalidate errors, but since topKey wasn't actually written to the graph before, it
    // will be rebuilt.
    tester.eval(/*keepGoing=*/ true, topKey);
  }

  @Test
  public void continueWithErrorDep() throws Exception {
    SkyKey afterKey = nonHermeticKey("after");
    SkyKey errorKey = skyKey("my_error_value");
    tester.getOrCreate(errorKey).setHasError(true);
    tester.set(afterKey, new StringValue("after"));
    SkyKey parentKey = skyKey("parent");
    tester
        .getOrCreate(parentKey)
        .addErrorDependency(errorKey, new StringValue("recovered"))
        .setComputedValue(CONCATENATE)
        .addDependency(afterKey);
    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ true, parentKey);
    assertThat(result.errorMap()).isEmpty();
    assertThat(result.get(parentKey).getValue()).isEqualTo("recoveredafter");
    tester.set(afterKey, new StringValue("before"));
    tester.invalidate();
    result = tester.eval(/*keepGoing=*/ true, parentKey);
    assertThat(result.errorMap()).isEmpty();
    assertThat(result.get(parentKey).getValue()).isEqualTo("recoveredbefore");
  }

  @Test
  public void continueWithErrorDepTurnedGood() throws Exception {
    SkyKey errorKey = nonHermeticKey("my_error_value");
    tester.getOrCreate(errorKey).setHasError(true);
    tester.set("after", new StringValue("after"));
    SkyKey parentKey = skyKey("parent");
    tester
        .getOrCreate(parentKey)
        .addErrorDependency(errorKey, new StringValue("recovered"))
        .setComputedValue(CONCATENATE)
        .addDependency("after");
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ true, parentKey);
    assertThat(result.errorMap()).isEmpty();
    assertThat(result.get(parentKey).getValue()).isEqualTo("recoveredafter");
    tester.set(errorKey, new StringValue("reformed")).setHasError(false);
    tester.invalidate();
    result = tester.eval(/*keepGoing=*/ true, parentKey);
    assertThat(result.errorMap()).isEmpty();
    assertThat(result.get(parentKey).getValue()).isEqualTo("reformedafter");
  }

  @Test
  public void errorDepAlreadyThereThenTurnedGood() throws Exception {
    SkyKey errorKey = nonHermeticKey("my_error_value");
    tester.getOrCreate(errorKey).setHasError(true);
    SkyKey parentKey = skyKey("parent");
    tester
        .getOrCreate(parentKey)
        .addErrorDependency(errorKey, new StringValue("recovered"))
        .setHasError(true);
    // Prime the graph by putting the error value in it beforehand.
    assertThat(tester.evalAndGetError(/*keepGoing=*/ true, errorKey)).isNotNull();
    // Request the parent.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, parentKey);
    assertThatEvaluationResult(result).hasSingletonErrorThat(parentKey);
    // Change the error value to no longer throw.
    tester.set(errorKey, new StringValue("reformed")).setHasError(false);
    tester
        .getOrCreate(parentKey, /*markAsModified=*/ false)
        .setHasError(false)
        .setComputedValue(COPY);
    tester.differencer.invalidate(ImmutableList.of(errorKey));
    tester.invalidate();
    // Request the parent again. This time it should succeed.
    result = tester.eval(/*keepGoing=*/ false, parentKey);
    assertThat(result.errorMap()).isEmpty();
    assertThat(result.get(parentKey).getValue()).isEqualTo("reformed");
    // Confirm that the parent no longer depends on the error transience value -- make it
    // unbuildable again, but without invalidating it, and invalidate transient errors. The parent
    // should not be rebuilt.
    tester.getOrCreate(parentKey, /*markAsModified=*/ false).setHasError(true);
    tester.invalidateTransientErrors();
    result = tester.eval(/*keepGoing=*/ false, parentKey);
    assertThat(result.errorMap()).isEmpty();
    assertThat(result.get(parentKey).getValue()).isEqualTo("reformed");
  }

  /**
   * Regression test for 2014 bug: error transience value is registered before newly requested deps.
   * A value requests a child, gets it back immediately, and then throws, causing the error
   * transience value to be registered as a dep. The following build, the error is invalidated via
   * that child.
   */
  @Test
  public void doubleDepOnErrorTransienceValue() throws Exception {
    SkyKey leafKey = nonHermeticKey("leaf");
    tester.set(leafKey, new StringValue("leaf"));
    // Prime the graph by putting leaf in beforehand.
    assertThat(tester.evalAndGet(/*keepGoing=*/ false, leafKey)).isEqualTo(new StringValue("leaf"));
    SkyKey topKey = skyKey("top");
    tester.getOrCreate(topKey).addDependency(leafKey).setHasError(true);
    // Build top -- it has an error.
    tester.evalAndGetError(/*keepGoing=*/ true, topKey);
    // Invalidate top via leaf, and rebuild.
    tester.set(leafKey, new StringValue("leaf2"));
    tester.invalidate();
    tester.evalAndGetError(/*keepGoing=*/ true, topKey);
  }

  /** Regression test for crash bug. */
  @Test
  public void errorTransienceDepCleared() throws Exception {
    SkyKey top = skyKey("top");
    SkyKey leaf = nonHermeticKey("leaf");
    tester.set(leaf, new StringValue("leaf"));
    tester.getOrCreate(top).addDependency(leaf).setHasTransientError(true);
    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ false, top);
    assertWithMessage(result.toString()).that(result.hasError()).isTrue();
    tester.getOrCreate(leaf, /* markAsModified= */ true);
    tester.invalidate();
    SkyKey irrelevant = skyKey("irrelevant");
    tester.set(irrelevant, new StringValue("irrelevant"));
    tester.eval(/* keepGoing= */ true, irrelevant);
    tester.invalidateTransientErrors();
    result = tester.eval(/*keepGoing=*/ true, top);
    assertWithMessage(result.toString()).that(result.hasError()).isTrue();
  }

  @Test
  public void incompleteValueAlreadyThereNotUsed() throws Exception {
    initializeTester();
    SkyKey errorKey = skyKey("my_error_value");
    tester.getOrCreate(errorKey).setHasError(true);
    SkyKey midKey = skyKey("mid");
    tester
        .getOrCreate(midKey)
        .addErrorDependency(errorKey, new StringValue("recovered"))
        .setComputedValue(COPY);
    SkyKey parentKey = skyKey("parent");
    tester
        .getOrCreate(parentKey)
        .addErrorDependency(midKey, new StringValue("don't use this"))
        .setComputedValue(COPY);
    // Prime the graph by evaluating the mid-level value. It shouldn't be stored in the graph
    // because it was only called during the bubbling-up phase.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, midKey);
    assertThat(result.get(midKey)).isNull();
    assertThatEvaluationResult(result).hasSingletonErrorThat(midKey);
    // In a keepGoing build, midKey should be re-evaluated.
    assertThat(((StringValue) tester.evalAndGet(/*keepGoing=*/ true, parentKey)).getValue())
        .isEqualTo("recovered");
  }

  /**
   * "top" requests a dependency group in which the first value, called "error", throws an
   * exception, so "mid" and "mid2", which depend on "slow", never get built.
   */
  @Test
  public void errorInDependencyGroup() throws Exception {
    SkyKey topKey = skyKey("top");
    CountDownLatch slowStart = new CountDownLatch(1);
    CountDownLatch errorFinish = new CountDownLatch(1);
    SkyKey errorKey = nonHermeticKey("error");
    tester
        .getOrCreate(errorKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ null,
                /*waitToFinish=*/ slowStart,
                /*notifyFinish=*/ errorFinish,
                /*waitForException=*/ false,
                // ChainedFunction throws when value is null.
                /*value=*/ null,
                /*deps=*/ ImmutableList.of()));
    SkyKey slowKey = skyKey("slow");
    tester
        .getOrCreate(slowKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ slowStart,
                /*waitToFinish=*/ errorFinish,
                /*notifyFinish=*/ null,
                /*waitForException=*/ true,
                new StringValue("slow"),
                /*deps=*/ ImmutableList.of()));
    SkyKey midKey = skyKey("mid");
    tester.getOrCreate(midKey).addDependency(slowKey).setComputedValue(COPY);
    SkyKey mid2Key = skyKey("mid2");
    tester.getOrCreate(mid2Key).addDependency(slowKey).setComputedValue(COPY);
    tester.set(topKey, null);
    tester
        .getOrCreate(topKey)
        .setBuilder(
            (skyKey, env) -> {
              env.getValuesAndExceptions(ImmutableList.of(errorKey, midKey, mid2Key));
              if (env.valuesMissing()) {
                return null;
              }
              return new StringValue("top");
            });

    // Assert that build fails and "error" really is in error.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, topKey);
    assertThat(result.hasError()).isTrue();
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(topKey);

    // Ensure that evaluation succeeds if errorKey does not throw an error.
    tester.getOrCreate(errorKey).setBuilder(null);
    tester.set(errorKey, new StringValue("ok"));
    tester.invalidate();
    assertThat(tester.evalAndGet("top")).isEqualTo(new StringValue("top"));
  }

  /**
   * Regression test -- if value top requests {depA, depB}, depC, with depA and depC there and depB
   * absent, and then throws an exception, the stored deps should be depA, depC (in different
   * groups), not {depA, depC} (same group).
   */
  @Test
  public void valueInErrorWithGroups() throws Exception {
    SkyKey topKey = skyKey("top");
    SkyKey groupDepA = nonHermeticKey("groupDepA");
    SkyKey groupDepB = skyKey("groupDepB");
    SkyKey depC = nonHermeticKey("depC");
    tester.set(groupDepA, new SkyKeyValue(depC));
    tester.set(groupDepB, new StringValue(""));
    tester.getOrCreate(depC).setHasError(true);
    tester
        .getOrCreate(topKey)
        .setBuilder(
            (skyKey, env) -> {
              SkyKeyValue val =
                  (SkyKeyValue)
                      env.getValuesAndExceptions(ImmutableList.of(groupDepA, groupDepB))
                          .get(groupDepA);
              if (env.valuesMissing()) {
                return null;
              }
              try {
                env.getValueOrThrow(val.key, SomeErrorException.class);
              } catch (SomeErrorException e) {
                throw new GenericFunctionException(e, Transience.PERSISTENT);
              }
              return env.valuesMissing() ? null : new StringValue("top");
            });

    EvaluationResult<SkyValue> evaluationResult = tester.eval(/*keepGoing=*/ true, groupDepA, depC);
    assertThat(((SkyKeyValue) evaluationResult.get(groupDepA)).key).isEqualTo(depC);
    assertThatEvaluationResult(evaluationResult).hasErrorEntryForKeyThat(depC);
    evaluationResult = tester.eval(/*keepGoing=*/ false, topKey);
    assertThatEvaluationResult(evaluationResult).hasErrorEntryForKeyThat(topKey);

    tester.set(groupDepA, new SkyKeyValue(groupDepB));
    tester.getOrCreate(depC, /*markAsModified=*/ true);
    tester.invalidate();
    evaluationResult = tester.eval(/*keepGoing=*/ false, topKey);
    assertWithMessage(evaluationResult.toString()).that(evaluationResult.hasError()).isFalse();
    assertThat(evaluationResult.get(topKey)).isEqualTo(new StringValue("top"));
  }

  private static class SkyKeyValue implements SkyValue {
    private final SkyKey key;

    private SkyKeyValue(SkyKey key) {
      this.key = key;
    }
  }

  @Test
  public void errorOnlyEmittedOnce() throws Exception {
    initializeTester();
    tester.set("x", new StringValue("y")).setWarning("fizzlepop");
    StringValue value = (StringValue) tester.evalAndGet("x");
    assertThat(value.getValue()).isEqualTo("y");
    assertThatEvents(eventCollector).containsExactly("fizzlepop");

    tester.invalidate();
    value = (StringValue) tester.evalAndGet("x");
    assertThat(value.getValue()).isEqualTo("y");
    // No new events emitted.
  }

  /**
   * We are checking here that we are resilient to a race condition in which a value that is
   * checking its children for dirtiness is signaled by all of its children, putting it in a ready
   * state, before the thread has terminated. Optionally, one of its children may throw an error,
   * shutting down the threadpool. The essential race is that a child about to throw signals its
   * parent and the parent's builder restarts itself before the exception is thrown. Here, the
   * signaling happens while dirty dependencies are being checked. We control the timing by blocking
   * "top"'s registering itself on its deps.
   */
  private void dirtyChildEnqueuesParentDuringCheckDependencies(boolean throwError)
      throws Exception {
    // Value to be built. It will be signaled to rebuild before it has finished checking its deps.
    SkyKey top = skyKey("a_top");
    // otherTop is alphabetically after top.
    SkyKey otherTop = skyKey("z_otherTop");
    // Dep that blocks before it acknowledges being added as a dep by top, so the firstKey value has
    // time to signal top. (Importantly its key is alphabetically after 'firstKey').
    SkyKey slowAddingDep = skyKey("slowDep");
    // Value that is modified on the second build. Its thread won't finish until it signals top,
    // which will wait for the signal before it enqueues its next dep. We prevent the thread from
    // finishing by having the graph listener block on the second reverse dep to signal.
    SkyKey firstKey = nonHermeticKey("first");
    tester.set(firstKey, new StringValue("biding"));
    // Don't perform any blocking on the first build.
    AtomicBoolean delayTopSignaling = new AtomicBoolean(false);
    CountDownLatch topSignaled = new CountDownLatch(1);
    CountDownLatch topRequestedDepOrRestartedBuild = new CountDownLatch(1);
    CountDownLatch parentsRequested = new CountDownLatch(2);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (!delayTopSignaling.get()) {
            return;
          }
          if (key.equals(otherTop) && type == EventType.SIGNAL) {
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                topRequestedDepOrRestartedBuild, "top's builder did not start in time");
            return;
          }
          if (key.equals(firstKey) && type == EventType.ADD_REVERSE_DEP && order == Order.AFTER) {
            parentsRequested.countDown();
            return;
          }
          if (key.equals(firstKey) && type == EventType.CHECK_IF_DONE && order == Order.AFTER) {
            parentsRequested.countDown();
            if (throwError) {
              topRequestedDepOrRestartedBuild.countDown();
            }
            return;
          }
          if (key.equals(top) && type == EventType.SIGNAL && order == Order.AFTER) {
            // top is signaled by firstKey (since slowAddingDep is blocking), so slowAddingDep
            // is now free to acknowledge top as a parent.
            topSignaled.countDown();
            return;
          }
          if (key.equals(firstKey) && type == EventType.SET_VALUE && order == Order.BEFORE) {
            // Make sure both parents add themselves as rdeps.
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                parentsRequested, "parents did not request dep in time");
          }
          if (key.equals(slowAddingDep)
              && type == EventType.CHECK_IF_DONE
              && top.equals(context)
              && order == Order.BEFORE) {
            // If top is trying to declare a dep on slowAddingDep, wait until firstKey has
            // signaled top. Then this add dep will return DONE and top will be signaled,
            // making it ready, so it will be enqueued.
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                topSignaled, "first key didn't signal top in time");
          }
        },
        /* deterministic= */ true);
    tester.set(slowAddingDep, new StringValue("dep"));
    AtomicInteger numTopInvocations = new AtomicInteger(0);
    tester
        .getOrCreate(top)
        .setBuilder(
            (key, env) -> {
              numTopInvocations.incrementAndGet();
              if (delayTopSignaling.get()) {
                // The graph listener will block on firstKey's signaling of otherTop above until
                // this thread starts running.
                topRequestedDepOrRestartedBuild.countDown();
              }
              // top's builder just requests both deps in a group.
              env.getValuesAndExceptions(ImmutableList.of(firstKey, slowAddingDep));
              return env.valuesMissing() ? null : new StringValue("top");
            });
    // First build : just prime the graph.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, top);
    assertThat(result.hasError()).isFalse();
    assertThat(result.get(top)).isEqualTo(new StringValue("top"));
    assertThat(numTopInvocations.get()).isEqualTo(2);
    // Now dirty the graph, and maybe have firstKey throw an error.
    if (throwError) {
      tester
          .getOrCreate(firstKey, /*markAsModified=*/ true)
          .setConstantValue(null)
          .setBuilder(
              new SkyFunction() {
                @Nullable
                @Override
                public SkyValue compute(SkyKey skyKey, Environment env)
                    throws SkyFunctionException {
                  TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                      parentsRequested, "both parents didn't request in time");
                  throw new GenericFunctionException(
                      new SomeErrorException(firstKey.toString()), Transience.PERSISTENT);
                }
              });
    } else {
      tester
          .getOrCreate(firstKey, /*markAsModified=*/ true)
          .setConstantValue(new StringValue("new"));
    }
    tester.getOrCreate(otherTop).addDependency(firstKey).setComputedValue(CONCATENATE);
    tester.invalidate();
    delayTopSignaling.set(true);
    result = tester.eval(/*keepGoing=*/ false, top, otherTop);
    if (throwError) {
      assertThatEvaluationResult(result).hasError();
      assertThat(result.keyNames()).isEmpty(); // No successfully evaluated values.
      assertThatEvaluationResult(result).hasErrorEntryForKeyThat(top);
      assertWithMessage(
              "on the incremental build, top's builder should have only been used in error "
                  + "bubbling")
          .that(numTopInvocations.get())
          .isEqualTo(3);
    } else {
      assertThatEvaluationResult(result).hasEntryThat(top).isEqualTo(new StringValue("top"));
      assertThatEvaluationResult(result).hasNoError();
      assertWithMessage(
              "on the incremental build, top's builder should have only been executed once in "
                  + "normal evaluation")
          .that(numTopInvocations.get())
          .isEqualTo(3);
    }
    assertThat(topSignaled.getCount()).isEqualTo(0);
    assertThat(topRequestedDepOrRestartedBuild.getCount()).isEqualTo(0);
  }

  @Test
  public void dirtyChildEnqueuesParentDuringCheckDependencies_ThrowDoesntEnqueue()
      throws Exception {
    dirtyChildEnqueuesParentDuringCheckDependencies(/*throwError=*/ true);
  }

  @Test
  public void dirtyChildEnqueuesParentDuringCheckDependencies_NoThrow() throws Exception {
    dirtyChildEnqueuesParentDuringCheckDependencies(/*throwError=*/ false);
  }

  @Test
  public void removeReverseDepFromRebuildingNode() throws Exception {
    SkyKey topKey = skyKey("top");
    SkyKey midKey = nonHermeticKey("mid");
    SkyKey changedKey = nonHermeticKey("changed");
    tester.getOrCreate(changedKey).setConstantValue(new StringValue("first"));
    // When top depends on mid,
    tester.getOrCreate(topKey).addDependency(midKey).setComputedValue(CONCATENATE);
    // And mid depends on changed,
    tester.getOrCreate(midKey).addDependency(changedKey).setComputedValue(CONCATENATE);
    CountDownLatch changedKeyStarted = new CountDownLatch(1);
    CountDownLatch changedKeyCanFinish = new CountDownLatch(1);
    AtomicBoolean controlTiming = new AtomicBoolean(false);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (!controlTiming.get()) {
            return;
          }
          if (key.equals(midKey) && type == EventType.CHECK_IF_DONE && order == Order.BEFORE) {
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                changedKeyStarted, "changed key didn't start");
          } else if (key.equals(changedKey)
              && type == EventType.REMOVE_REVERSE_DEP
              && order == Order.AFTER
              && midKey.equals(context)) {
            changedKeyCanFinish.countDown();
          }
        },
        /* deterministic= */ false);
    // Then top builds as expected.
    assertThat(tester.evalAndGet(/*keepGoing=*/ false, topKey)).isEqualTo(new StringValue("first"));
    // When changed is modified,
    tester
        .getOrCreate(changedKey, /*markAsModified=*/ true)
        .setConstantValue(null)
        .setBuilder(
            // And changed is not allowed to finish building until it is released,
            new ChainedFunction(
                changedKeyStarted,
                changedKeyCanFinish,
                null,
                false,
                new StringValue("second"),
                ImmutableList.of()));
    // And mid is independently marked as modified,
    tester
        .getOrCreate(midKey, /*markAsModified=*/ true)
        .removeDependency(changedKey)
        .setComputedValue(null)
        .setConstantValue(new StringValue("mid"));
    tester.invalidate();
    SkyKey newTopKey = skyKey("newTop");
    // And changed will start rebuilding independently of midKey, because it's requested directly by
    // newTop
    tester.getOrCreate(newTopKey).addDependency(changedKey).setComputedValue(CONCATENATE);
    // And we control the timing using the graph listener above to make sure that:
    // (1) before we do anything with mid, changed has already started, and
    // (2) changed key can't finish until mid tries to remove its reverse dep from changed,
    controlTiming.set(true);
    // Then this evaluation completes without crashing.
    tester.eval(/*keepGoing=*/ false, newTopKey, topKey);
  }

  @Test
  public void dirtyThenDeleted() throws Exception {
    SkyKey topKey = nonHermeticKey("top");
    SkyKey leafKey = nonHermeticKey("leaf");
    tester.getOrCreate(topKey).addDependency(leafKey).setComputedValue(CONCATENATE);
    tester.set(leafKey, new StringValue("leafy"));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, topKey))
        .isEqualTo(new StringValue("leafy"));
    tester.getOrCreate(topKey, /* markAsModified= */ true);
    tester.invalidate();
    assertThat(tester.evalAndGet(/* keepGoing= */ false, leafKey))
        .isEqualTo(new StringValue("leafy"));
    tester.delete("top");
    tester.getOrCreate(leafKey, /* markAsModified= */ true);
    tester.invalidate();
    assertThat(tester.evalAndGet(/* keepGoing= */ false, leafKey))
        .isEqualTo(new StringValue("leafy"));
  }

  /**
   * Basic test for a {@link SkyFunction.Reset} with no rewinding of dependencies.
   *
   * <p>Ensures that {@link NodeEntry#getResetDirectDeps} is used correctly by Skyframe to avoid
   * registering duplicate rdep edges when {@code dep} is requested both before and after a reset.
   *
   * <p>This test covers the case where {@code dep} is newly requested post-reset during a {@link
   * SkyFunction#compute} invocation that returns a {@link SkyValue}, which exercises a different
   * {@link AbstractParallelEvaluator} code path than the scenario covered by {@link
   * #resetSelfOnly_extraDepMissingAfterReset_initialBuild}.
   */
  @Test
  public void resetSelfOnly_singleDep_initialBuild() throws Exception {
    assume().that(resetSupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    SkyKey top = skyKey("top");
    SkyKey dep = skyKey("dep");

    tester
        .getOrCreate(top)
        .setBuilder(
            new SkyFunction() {
              private boolean alreadyReset = false;

              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                var depValue = env.getValue(dep);
                if (depValue == null) {
                  return null;
                }
                if (!alreadyReset) {
                  alreadyReset = true;
                  return Reset.selfOnly(top);
                }
                return new StringValue("topVal");
              }
            });
    tester.getOrCreate(dep).setConstantValue(new StringValue("depVal"));

    var result = tester.eval(/* keepGoing= */ false, top);

    assertThatEvaluationResult(result).hasEntryThat(top).isEqualTo(new StringValue("topVal"));
    assertThat(inconsistencyReceiver).containsExactly(InconsistencyData.resetRequested(top));

    if (!incrementalitySupported()) {
      return; // Skip assertions on dependency edges when they aren't kept.
    }

    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(dep).containsExactly(top);
    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(top).containsExactly(dep);
  }

  /**
   * Similar to {@link #resetSelfOnly_singleDep_initialBuild} except that the reset occurs on the
   * node's incremental build.
   */
  @Test
  public void resetSelfOnly_singleDep_incrementalBuild() throws Exception {
    assume().that(resetSupported()).isTrue();
    assume().that(incrementalitySupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    SkyKey top = skyKey("top");
    SkyKey dep = nonHermeticKey("dep");

    tester
        .getOrCreate(top)
        .setBuilder(
            new SkyFunction() {
              private boolean alreadyReset = false;

              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                var depValue = (StringValue) env.getValue(dep);
                if (depValue == null) {
                  return null;
                }
                if (depValue.getValue().equals("depVal2") && !alreadyReset) {
                  alreadyReset = true;
                  return Reset.selfOnly(top);
                }
                return new StringValue("topVal");
              }
            });

    tester.getOrCreate(dep).setConstantValue(new StringValue("depVal1"));
    tester.eval(/* keepGoing= */ false, top);
    assertThat(inconsistencyReceiver).isEmpty();

    tester.set(dep, new StringValue("depVal2"));
    tester.invalidate();
    var result = tester.eval(/* keepGoing= */ false, top);

    assertThatEvaluationResult(result).hasEntryThat(top).isEqualTo(new StringValue("topVal"));
    assertThat(inconsistencyReceiver).containsExactly(InconsistencyData.resetRequested(top));
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(dep).containsExactly(top);
    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(top).containsExactly(dep);
  }

  /**
   * Test for a {@link SkyFunction.Reset} with no rewinding of dependencies, with a missing
   * dependency requested post-reset.
   *
   * <p>Ensures that {@link NodeEntry#getResetDirectDeps} is used correctly by Skyframe to avoid
   * registering duplicate rdep edges when {@code dep} is requested both before and after a reset.
   *
   * <p>This test covers the case where {@code dep} is newly requested post-reset in a {@link
   * SkyFunction#compute} invocation that returns {@code null} (because {@code extraDep} is
   * missing), which exercises a different {@link AbstractParallelEvaluator} code path than the
   * scenario covered by {@link #resetSelfOnly_singleDep_initialBuild}.
   */
  @Test
  public void resetSelfOnly_extraDepMissingAfterReset_initialBuild() throws Exception {
    assume().that(resetSupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    SkyKey top = skyKey("top");
    SkyKey dep = skyKey("dep");
    SkyKey extraDep = skyKey("extraDep");

    tester
        .getOrCreate(top)
        .setBuilder(
            new SkyFunction() {
              private boolean alreadyReset = false;

              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                var depValue = env.getValue(dep);
                if (depValue == null) {
                  return null;
                }
                if (!alreadyReset) {
                  alreadyReset = true;
                  return Reset.selfOnly(top);
                }
                var extraDepValue = env.getValue(extraDep);
                if (extraDepValue == null) {
                  return null;
                }
                return new StringValue("topVal");
              }
            });
    tester.getOrCreate(dep).setConstantValue(new StringValue("depVal"));
    tester.getOrCreate(extraDep).setConstantValue(new StringValue("extraDepVal"));

    var result = tester.eval(/* keepGoing= */ false, top);

    assertThatEvaluationResult(result).hasEntryThat(top).isEqualTo(new StringValue("topVal"));
    assertThat(inconsistencyReceiver).containsExactly(InconsistencyData.resetRequested(top));

    if (!incrementalitySupported()) {
      return; // Skip assertions on dependency edges when they aren't kept.
    }

    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(dep).containsExactly(top);
    assertThatEvaluationResult(result)
        .hasDirectDepsInGraphThat(top)
        .containsExactly(dep, extraDep)
        .inOrder();
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(extraDep).containsExactly(top);
  }

  /**
   * Similar to {@link #resetSelfOnly_extraDepMissingAfterReset_initialBuild} except that the reset
   * occurs on the node's incremental build.
   */
  @Test
  public void resetSelfOnly_extraDepMissingAfterReset_incrementalBuild() throws Exception {
    assume().that(resetSupported()).isTrue();
    assume().that(incrementalitySupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    SkyKey top = skyKey("top");
    SkyKey dep = nonHermeticKey("dep");
    SkyKey extraDep = skyKey("extraDep");

    tester
        .getOrCreate(top)
        .setBuilder(
            new SkyFunction() {
              private boolean alreadyReset = false;

              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                var depValue = (StringValue) env.getValue(dep);
                if (depValue == null) {
                  return null;
                }
                if (depValue.getValue().equals("depVal2") && !alreadyReset) {
                  alreadyReset = true;
                  return Reset.selfOnly(top);
                }
                var extraDepValue = env.getValue(extraDep);
                if (extraDepValue == null) {
                  return null;
                }
                return new StringValue("topVal");
              }
            });
    tester.getOrCreate(dep).setConstantValue(new StringValue("depVal1"));
    tester.getOrCreate(extraDep).setConstantValue(new StringValue("extraDepVal"));
    tester.eval(/* keepGoing= */ false, top);
    assertThat(inconsistencyReceiver).isEmpty();

    tester.set(dep, new StringValue("depVal2"));
    tester.invalidate();
    var result = tester.eval(/* keepGoing= */ false, top);

    assertThatEvaluationResult(result).hasEntryThat(top).isEqualTo(new StringValue("topVal"));
    assertThat(inconsistencyReceiver).containsExactly(InconsistencyData.resetRequested(top));
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(dep).containsExactly(top);
    assertThatEvaluationResult(result)
        .hasDirectDepsInGraphThat(top)
        .containsExactly(dep, extraDep)
        .inOrder();
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(extraDep).containsExactly(top);
  }

  /**
   * Tests that if a dependency is requested prior to a {@link SkyFunction.Reset} but not after,
   * then the corresponding reverse dep edge is removed.
   *
   * <p>This happens in practice with input-discovering actions, which use mutable state to track
   * input discovery, resulting in unstable dependencies.
   */
  @Test
  public void resetSelfOnly_depNotRequestedAgainAfterReset() throws Exception {
    assume().that(resetSupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    SkyKey top = skyKey("top");
    SkyKey flakyDep = skyKey("flakyDep");
    SkyKey stableDep = skyKey("stableDep");

    tester
        .getOrCreate(top)
        .setBuilder(
            new SkyFunction() {
              private boolean alreadyReset = false;

              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                env.getValuesAndExceptions(
                    alreadyReset
                        ? ImmutableList.of(stableDep)
                        : ImmutableList.of(stableDep, flakyDep));
                if (env.valuesMissing()) {
                  return null;
                }
                if (!alreadyReset) {
                  alreadyReset = true;
                  return Reset.selfOnly(top);
                }
                return new StringValue("topVal");
              }
            });
    tester.getOrCreate(stableDep).setConstantValue(new StringValue("stableDepVal"));
    tester.getOrCreate(flakyDep).setConstantValue(new StringValue("flakyDepVal"));

    var result = tester.eval(/* keepGoing= */ false, top);

    assertThatEvaluationResult(result).hasEntryThat(top).isEqualTo(new StringValue("topVal"));
    assertThat(inconsistencyReceiver).containsExactly(InconsistencyData.resetRequested(top));

    if (!incrementalitySupported()) {
      return; // Skip assertions on dependency edges when they aren't kept.
    }

    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(top).containsExactly(stableDep);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(stableDep).containsExactly(top);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(flakyDep).isEmpty();
  }

  /**
   * Tests that reset nodes are properly handled during invalidation after an aborted evaluation.
   *
   * <p>Invalidation deletes any nodes that are incomplete from the prior evaluation (in this case
   * {@code top}). It should also remove the corresponding reverse dep edge from {@code dep} even
   * though {@code top} does not have {@code dep} as a temporary direct dep when the evaluation is
   * aborted.
   *
   * <p>An aborted evaluation can happen in practice when there is an error on a {@code
   * --nokeep_going} build or if the user hits ctrl+c.
   */
  @Test
  public void resetSelfOnly_evaluationAborted() throws Exception {
    assume().that(resetSupported()).isTrue();
    assume().that(incrementalitySupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    SkyKey top = skyKey("top");
    SkyKey dep = skyKey("dep");

    tester
        .getOrCreate(top)
        .setBuilder(
            new SkyFunction() {
              private boolean alreadyReset = false;

              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                if (alreadyReset) {
                  throw new InterruptedException("Evaluation aborted");
                }
                var depValue = env.getValue(dep);
                if (depValue == null) {
                  return null;
                }
                alreadyReset = true;
                return Reset.selfOnly(top);
              }
            });
    tester.getOrCreate(dep).setConstantValue(new StringValue("depVal"));

    assertThrows(InterruptedException.class, () -> tester.eval(/* keepGoing= */ false, top));
    assertThat(inconsistencyReceiver).containsExactly(InconsistencyData.resetRequested(top));
    inconsistencyReceiver.clear();

    var result = tester.eval(/* keepGoing= */ false, dep);

    assertThatEvaluationResult(result).hasEntryThat(dep).isEqualTo(new StringValue("depVal"));
    assertThat(inconsistencyReceiver).isEmpty();
    assertThat(tester.evaluator.getValues()).doesNotContainKey(top);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(dep).isEmpty();
  }

  /** Basic test of rewinding. */
  @Test
  public void rewindOneDep() throws Exception {
    assume().that(resetSupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    var rewindableFunction = new RewindableFunction();
    SkyKey top = skyKey("top");
    SkyKey dep = skyKey("dep");

    tester.getOrCreate(dep).setBuilder(rewindableFunction);
    tester
        .getOrCreate(top)
        .setBuilder(
            (skyKey, env) -> {
              var depValue = (StringValue) env.getValue(dep);
              if (depValue == null) {
                return null;
              }
              if (depValue.equals(RewindableFunction.STALE_VALUE)) {
                var rewindGraph = Reset.newRewindGraphFor(top);
                rewindGraph.putEdge(top, dep);
                return Reset.of(rewindGraph);
              }
              assertThat(depValue).isEqualTo(RewindableFunction.FRESH_VALUE);
              return new StringValue("topVal");
            });

    var result = tester.eval(/* keepGoing= */ false, top);

    assertThatEvaluationResult(result).hasEntryThat(top).isEqualTo(new StringValue("topVal"));
    assertThat(inconsistencyReceiver)
        .containsExactly(
            InconsistencyData.resetRequested(top),
            InconsistencyData.rewind(top, ImmutableSet.of(dep)));
    assertThat(rewindableFunction.calls).isEqualTo(2);

    if (!incrementalitySupported()) {
      return; // Skip assertions on dependency edges when they aren't kept.
    }

    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(dep).containsExactly(top);
    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(top).containsExactly(dep);
  }

  /**
   * Tests the case where multiple parents attempt to rewind the same node concurrently, one
   * successfully dirties the node, and the other observes the node as already dirty.
   */
  @Test
  public void twoParentsRewindSameDep_markedDirtyOnce() throws Exception {
    assume().that(resetSupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    var rewindableFunction = new RewindableFunction();
    CyclicBarrier parentBarrier = new CyclicBarrier(2);
    SkyKey top1 = skyKey("top1");
    SkyKey top2 = skyKey("top2");
    SkyKey dep = skyKey("dep");

    tester.getOrCreate(dep).setBuilder(rewindableFunction);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (type == EventType.MARK_DIRTY && order == Order.AFTER) {
            awaitUnchecked(parentBarrier);
          }
        },
        /* deterministic= */ false);
    SkyFunction parentFunction =
        (skyKey, env) -> {
          var depValue = (StringValue) env.getValue(dep);
          if (depValue == null) {
            return null;
          }
          if (depValue.equals(RewindableFunction.STALE_VALUE)) {
            awaitUnchecked(parentBarrier);
            var rewindGraph = Reset.newRewindGraphFor(skyKey);
            rewindGraph.putEdge(skyKey, dep);
            return Reset.of(rewindGraph);
          }
          assertThat(depValue).isEqualTo(RewindableFunction.FRESH_VALUE);
          return new StringValue("topVal");
        };
    tester.getOrCreate(top1).setBuilder(parentFunction);
    tester.getOrCreate(top2).setBuilder(parentFunction);

    var result = tester.eval(/* keepGoing= */ false, top1, top2);

    assertThatEvaluationResult(result).hasEntryThat(top1).isEqualTo(new StringValue("topVal"));
    assertThatEvaluationResult(result).hasEntryThat(top2).isEqualTo(new StringValue("topVal"));
    assertThat(inconsistencyReceiver)
        .containsExactly(
            InconsistencyData.resetRequested(top1),
            InconsistencyData.rewind(top1, ImmutableSet.of(dep)),
            InconsistencyData.resetRequested(top2),
            InconsistencyData.rewind(top2, ImmutableSet.of(dep)));
    assertThat(rewindableFunction.calls).isEqualTo(2);

    if (!incrementalitySupported()) {
      return; // Skip assertions on dependency edges when they aren't kept.
    }

    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(top1).containsExactly(dep);
    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(top2).containsExactly(dep);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(dep).containsExactly(top1, top2);
  }

  /**
   * Tests the case where multiple parents attempt to rewind the same node concurrently and one
   * successfully dirties the node, which then completes before the second parent dirties the node
   * again.
   */
  @Test
  public void twoParentsRewindSameDep_markedDirtyTwice() throws Exception {
    assume().that(resetSupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    var rewindableFunction = new RewindableFunction();
    CyclicBarrier parentBarrier = new CyclicBarrier(2);
    AtomicBoolean isFirstParent = new AtomicBoolean(true);
    CountDownLatch firstParentDone = new CountDownLatch(1);
    SkyKey top1 = skyKey("top1");
    SkyKey top2 = skyKey("top2");
    SkyKey dep = skyKey("dep");

    tester.getOrCreate(dep).setBuilder(rewindableFunction);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (type == EventType.MARK_DIRTY
              && order == Order.BEFORE
              && !isFirstParent.getAndSet(false)) {
            // Lost the race. Wait for the first parent to finish so we rewind again. We could just
            // wait for dep to finish, but then we might mark it dirty before the first parent uses
            // it, which would lead to flaky BUILDING_PARENT_FOUND_UNDONE_CHILD inconsistencies.
            Uninterruptibles.awaitUninterruptibly(firstParentDone);
          }
        },
        /* deterministic= */ false);
    SkyFunction parentFunction =
        (skyKey, env) -> {
          var depValue = (StringValue) env.getValue(dep);
          if (depValue == null) {
            return null;
          }
          if (depValue.equals(RewindableFunction.STALE_VALUE)) {
            awaitUnchecked(parentBarrier);
            var rewindGraph = Reset.newRewindGraphFor(skyKey);
            rewindGraph.putEdge(skyKey, dep);
            return Reset.of(rewindGraph);
          }
          assertThat(depValue).isEqualTo(RewindableFunction.FRESH_VALUE);
          firstParentDone.countDown();
          return new StringValue("topVal");
        };
    tester.getOrCreate(top1).setBuilder(parentFunction);
    tester.getOrCreate(top2).setBuilder(parentFunction);

    var result = tester.eval(/* keepGoing= */ false, top1, top2);

    assertThatEvaluationResult(result).hasEntryThat(top1).isEqualTo(new StringValue("topVal"));
    assertThatEvaluationResult(result).hasEntryThat(top2).isEqualTo(new StringValue("topVal"));
    assertThat(inconsistencyReceiver)
        .containsExactly(
            InconsistencyData.resetRequested(top1),
            InconsistencyData.rewind(top1, ImmutableSet.of(dep)),
            InconsistencyData.resetRequested(top2),
            InconsistencyData.rewind(top2, ImmutableSet.of(dep)));
    assertThat(rewindableFunction.calls).isEqualTo(3);

    if (!incrementalitySupported()) {
      return; // Skip assertions on dependency edges when they aren't kept.
    }

    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(top1).containsExactly(dep);
    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(top2).containsExactly(dep);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(dep).containsExactly(top1, top2);
  }

  /**
   * Regression test for b/315301248.
   *
   * <p>In a {@code --nokeep_going} build, multiple parents attempt to rewind the same node
   * concurrently. One successfully dirties the node, which then completes with an error before the
   * second parent attempts to dirty the node again. If the second rewinding attempt actually
   * transitions the node from done (in error) to dirty, we would crash during error bubbling, which
   * reasonably expects the errorful node to be done.
   *
   * <p>The solution is to ignore rewinding attempts on errorful nodes.
   */
  @Test
  public void twoParentsRewindSameDep_depEvaluatesToErrorAfterRewind() throws Exception {
    assume().that(resetSupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    var rewindableErrorFunction =
        new SkyFunction() {
          private int calls = 0;

          @Nullable
          @Override
          public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
            if (++calls == 1) {
              return RewindableFunction.STALE_VALUE;
            }
            throw new GenericFunctionException(new SomeErrorException("error"));
          }
        };
    CyclicBarrier parentBarrier = new CyclicBarrier(2);
    AtomicBoolean isFirstParent = new AtomicBoolean(true);
    CountDownLatch depErrorSet = new CountDownLatch(1);
    SkyKey top1 = skyKey("top1");
    SkyKey top2 = skyKey("top2");
    SkyKey dep = skyKey("dep");

    tester.getOrCreate(dep).setBuilder(rewindableErrorFunction);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (type == EventType.MARK_DIRTY
              && order == Order.BEFORE
              && !isFirstParent.getAndSet(false)) {
            // Lost the race. Wait for dep have its error set so that we attempt to rewind a done
            // node in error.
            Uninterruptibles.awaitUninterruptibly(depErrorSet);
          } else if (key.equals(dep)
              && type == EventType.SET_VALUE
              && order == Order.AFTER
              && ValueWithMetadata.getMaybeErrorInfo((SkyValue) context) != null) {
            depErrorSet.countDown();
          }
        },
        /* deterministic= */ false);
    SkyFunction parentFunction =
        (skyKey, env) -> {
          var depValue = (StringValue) env.getValue(dep);
          if (depValue == null) {
            return null;
          }
          assertThat(depValue).isEqualTo(RewindableFunction.STALE_VALUE);
          awaitUnchecked(parentBarrier);
          var rewindGraph = Reset.newRewindGraphFor(skyKey);
          rewindGraph.putEdge(skyKey, dep);
          return Reset.of(rewindGraph);
        };
    tester.getOrCreate(top1).setBuilder(parentFunction);
    tester.getOrCreate(top2).setBuilder(parentFunction);

    var result = tester.eval(/* keepGoing= */ false, top1, top2);

    assertThatEvaluationResult(result).hasError();
    assertThat(result.errorMap().keySet()).containsAnyOf(top1, top2);
    assertThat(inconsistencyReceiver)
        .containsExactly(
            InconsistencyData.resetRequested(top1),
            InconsistencyData.rewind(top1, ImmutableSet.of(dep)),
            InconsistencyData.resetRequested(top2),
            InconsistencyData.rewind(top2, ImmutableSet.of(dep)));

    if (!incrementalitySupported()) {
      return; // Skip assertions on dependency edges when they aren't kept.
    }

    result = tester.eval(/* keepGoing= */ false, dep);

    // The parents never completed, so an incremental build deletes them. Check that they are no
    // longer in the graph and that rdeps are removed from dep.
    assertThatEvaluationResult(result).hasSingletonErrorThat(dep).isNotNull();
    assertThat(tester.evaluator.getValues().keySet()).containsNoneOf(top1, top2);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(dep).isEmpty();
  }

  /**
   * Tests that when a node is rewound and evaluates to an error, its reverse transitive closure is
   * deleted from the graph, including parents that were done before rewinding took place.
   */
  @Test
  public void depWithDoneParentEvaluatesToErrorAfterRewind_reverseTransitiveClosureDeleted()
      throws Exception {
    assume().that(resetSupported()).isTrue();
    assume().that(incrementalitySupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    var rewindableErrorFunction =
        new SkyFunction() {
          private int calls = 0;

          @Nullable
          @Override
          public SkyValue compute(SkyKey skyKey, Environment env) throws SkyFunctionException {
            if (++calls == 1) {
              return RewindableFunction.STALE_VALUE;
            }
            throw new GenericFunctionException(new SomeErrorException("error"));
          }
        };
    CountDownLatch goodTopDone = new CountDownLatch(1);
    SkyKey goodTop = skyKey("goodTop");
    SkyKey badTop = skyKey("badTop");
    SkyKey dep = nonHermeticKey("dep");

    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (key.equals(goodTop) && type == EventType.SET_VALUE && order == Order.AFTER) {
            goodTopDone.countDown();
          }
        },
        /* deterministic= */ false);
    tester.getOrCreate(dep).setBuilder(rewindableErrorFunction);
    tester.getOrCreate(goodTop).addDependency(dep).setComputedValue(COPY);
    tester
        .getOrCreate(badTop)
        .setBuilder(
            (skyKey, env) -> {
              if (env.getValue(dep) == null) {
                return null;
              }
              goodTopDone.await();
              var rewindGraph = Reset.newRewindGraphFor(badTop);
              rewindGraph.putEdge(badTop, dep);
              return Reset.of(rewindGraph);
            });

    var result = tester.eval(/* keepGoing= */ false, goodTop, badTop);

    assertThatEvaluationResult(result).hasError();
    assertThat(result.errorMap().keySet()).containsExactly(badTop);
    assertThatEvaluationResult(result)
        .hasEntryThat(goodTop)
        .isEqualTo(RewindableFunction.STALE_VALUE);
    assertThat(inconsistencyReceiver)
        .containsExactly(
            InconsistencyData.resetRequested(badTop),
            InconsistencyData.rewind(badTop, ImmutableSet.of(dep)));

    result = tester.eval(/* keepGoing= */ false, new SkyKey[0]);

    assertThatEvaluationResult(result).hasNoError();
    assertThat(tester.getEvaluator().getValues().keySet()).containsNoneOf(dep, badTop, goodTop);
  }

  private static void awaitUnchecked(CyclicBarrier barrier) {
    try {
      barrier.await();
    } catch (InterruptedException | BrokenBarrierException e) {
      throw new IllegalStateException(e);
    }
  }

  /**
   * Test for a rewind graph with depth > 1.
   *
   * <p>Since {@code mid} simply propagates the value of {@code bottom}, {@code top} must rewind
   * both {@code mid} and {@code bottom}. See {@link
   * com.google.devtools.build.lib.actions.ActionExecutionMetadata#mayInsensitivelyPropagateInputs}
   * for the case that this test is simulating.
   */
  @Test
  public void rewindTransitiveDep() throws Exception {
    assume().that(resetSupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    var rewindableFunction = new RewindableFunction();
    SkyKey top = skyKey("top");
    SkyKey mid = skyKey("mid");
    SkyKey bottom = skyKey("bottom");

    tester.getOrCreate(bottom).setBuilder(rewindableFunction);
    tester.getOrCreate(mid).addDependency(bottom).setComputedValue(COPY);
    tester
        .getOrCreate(top)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                var midValue = (StringValue) env.getValue(mid);
                if (midValue == null) {
                  return null;
                }
                if (midValue.equals(RewindableFunction.STALE_VALUE)) {
                  var rewindGraph = Reset.newRewindGraphFor(top);
                  rewindGraph.putEdge(top, mid);
                  rewindGraph.putEdge(mid, bottom);
                  return Reset.of(rewindGraph);
                }
                assertThat(midValue).isEqualTo(RewindableFunction.FRESH_VALUE);
                return new StringValue("topVal");
              }
            });

    var result = tester.eval(/* keepGoing= */ false, top);

    assertThatEvaluationResult(result).hasEntryThat(top).isEqualTo(new StringValue("topVal"));
    assertThat(inconsistencyReceiver)
        .containsExactly(
            InconsistencyData.resetRequested(top),
            InconsistencyData.rewind(top, ImmutableSet.of(mid, bottom)));
    assertThat(rewindableFunction.calls).isEqualTo(2);

    if (!incrementalitySupported()) {
      return; // Skip assertions on dependency edges when they aren't kept.
    }

    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(top).containsExactly(mid);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(mid).containsExactly(top);
    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(mid).containsExactly(bottom);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(bottom).containsExactly(mid);
  }

  /**
   * Tests that incompletely rewound nodes are properly handled during invalidation after an aborted
   * evaluation.
   *
   * <p>Covers the concern described at b/149243918#comment9: without rewinding, we have an
   * invariant that after an evaluation, a done node cannot depend on a dirty node. The invalidator
   * leverges this invariant by short-circuiting when it visits a dirty node, under the assumption
   * that any rdeps are either already dirty or present in the invalidation frontier.
   *
   * <p>In this test, a value propagates from {@code bottom} to {@code mid} to {@code goodTop}.
   * However, after {@code goodTop} is done, {@code badTop} rewinds {@code mid}, and then the
   * evaluation is aborted. On the incremental build, {@code bottom} changes. We must recompute
   * {@code goodTop}, but the only path from {@code bottom} to {@code goodTop} goes through {@code
   * mid}, which is dirty, and so the invalidator will never visit {@code goodTop}.
   *
   * <p>The solution: instead of relying on bottom-up invalidation, rewound nodes are treated like
   * inflight nodes and deleted (along with their reverse transitive closure) prior to the next
   * evaluation.
   */
  @Test
  public void evaluationAbortedWithRewoundNodeOnInvalidationPath_dirty() throws Exception {
    assume().that(resetSupported()).isTrue();
    assume().that(incrementalitySupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    CountDownLatch goodTopDone = new CountDownLatch(1);
    SkyKey goodTop = skyKey("goodTop");
    SkyKey badTop = skyKey("badTop");
    SkyKey mid = skyKey("mid");
    SkyKey bottom = nonHermeticKey("bottom");

    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (key.equals(goodTop) && type == EventType.SET_VALUE && order == Order.AFTER) {
            goodTopDone.countDown();
          }
        },
        /* deterministic= */ false);
    tester.getOrCreate(goodTop).addDependency(mid).setComputedValue(COPY);
    tester
        .getOrCreate(badTop)
        .setBuilder(
            new SkyFunction() {
              private boolean alreadyReset = false;

              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                if (alreadyReset) {
                  throw new InterruptedException("Evaluation aborted");
                }
                if (env.getValue(mid) == null) {
                  return null;
                }
                goodTopDone.await();
                alreadyReset = true;
                var rewindGraph = Reset.newRewindGraphFor(badTop);
                rewindGraph.putEdge(badTop, mid);
                return Reset.of(rewindGraph);
              }
            });
    tester.getOrCreate(mid).addDependency(bottom).setComputedValue(COPY);
    tester.getOrCreate(bottom).setConstantValue(new StringValue("val1"));

    assertThrows(
        InterruptedException.class, () -> tester.eval(/* keepGoing= */ false, goodTop, badTop));
    assertThat(inconsistencyReceiver)
        .containsExactly(
            InconsistencyData.resetRequested(badTop),
            InconsistencyData.rewind(badTop, ImmutableSet.of(mid)));

    tester.set(bottom, new StringValue("val2"));
    tester.invalidate();
    var result = tester.eval(/* keepGoing= */ false, goodTop);

    assertThatEvaluationResult(result).hasEntryThat(goodTop).isEqualTo(new StringValue("val2"));
    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(goodTop).containsExactly(mid);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(mid).containsExactly(goodTop);
    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(mid).containsExactly(bottom);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(bottom).containsExactly(mid);
  }

  /**
   * Similar to {@link #evaluationAbortedWithRewoundNodeOnInvalidationPath_dirty} except that the
   * rewound node is inflight when the evaluation is aborted, so this actually works without the
   * special handling added for rewound nodes.
   */
  @Test
  public void evaluationAbortedWithRewoundNodeOnInvalidationPath_inflight() throws Exception {
    assume().that(resetSupported()).isTrue();
    assume().that(incrementalitySupported()).isTrue();

    var inconsistencyReceiver = recordInconsistencies();
    CountDownLatch goodTopDone = new CountDownLatch(1);
    AtomicBoolean rewindingInProgress = new AtomicBoolean(false);
    SkyKey goodTop = skyKey("goodTop");
    SkyKey badTop = skyKey("badTop");
    SkyKey mid = nonHermeticKey("mid");
    SkyKey bottom = nonHermeticKey("bottom");

    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (key.equals(goodTop) && type == EventType.SET_VALUE && order == Order.AFTER) {
            goodTopDone.countDown();
          }
        },
        /* deterministic= */ false);
    tester.getOrCreate(goodTop).addDependency(mid).setComputedValue(COPY);
    tester
        .getOrCreate(badTop)
        .setBuilder(
            (skyKey, env) -> {
              if (env.getValue(mid) == null) {
                return null;
              }
              goodTopDone.await();
              rewindingInProgress.set(true);
              var rewindGraph = Reset.newRewindGraphFor(badTop);
              rewindGraph.putEdge(badTop, mid);
              return Reset.of(rewindGraph);
            });
    tester
        .getOrCreate(mid)
        .setBuilder(
            (skyKey, env) -> {
              if (rewindingInProgress.get()) {
                throw new InterruptedException("Evaluation aborted");
              }
              return env.getValue(bottom);
            });
    tester.getOrCreate(bottom).setConstantValue(new StringValue("val1"));

    assertThrows(
        InterruptedException.class, () -> tester.eval(/* keepGoing= */ false, goodTop, badTop));
    assertThat(inconsistencyReceiver)
        .containsExactly(
            InconsistencyData.resetRequested(badTop),
            InconsistencyData.rewind(badTop, ImmutableSet.of(mid)));

    rewindingInProgress.set(false);
    tester.set(bottom, new StringValue("val2"));
    tester.invalidate();
    var result = tester.eval(/* keepGoing= */ false, goodTop);

    assertThatEvaluationResult(result).hasEntryThat(goodTop).isEqualTo(new StringValue("val2"));
    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(goodTop).containsExactly(mid);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(mid).containsExactly(goodTop);
    assertThatEvaluationResult(result).hasDirectDepsInGraphThat(mid).containsExactly(bottom);
    assertThatEvaluationResult(result).hasReverseDepsInGraphThat(bottom).containsExactly(mid);
  }

  private RecordingInconsistencyReceiver recordInconsistencies() {
    var inconsistencyReceiver = new RecordingInconsistencyReceiver();
    tester.setGraphInconsistencyReceiver(inconsistencyReceiver);
    tester.initialize();
    return inconsistencyReceiver;
  }

  private static final class RecordingInconsistencyReceiver
      implements GraphInconsistencyReceiver, Iterable<InconsistencyData> {
    private final List<InconsistencyData> inconsistencies = new ArrayList<>();

    @Override
    public synchronized void noteInconsistencyAndMaybeThrow(
        SkyKey key, @Nullable Collection<SkyKey> otherKeys, Inconsistency inconsistency) {
      inconsistencies.add(InconsistencyData.create(key, otherKeys, inconsistency));
    }

    @Override
    public Iterator<InconsistencyData> iterator() {
      return inconsistencies.iterator();
    }

    void clear() {
      inconsistencies.clear();
    }
  }

  /**
   * {@link SkyFunction} for rewinding tests that returns {@link #STALE_VALUE} the first time and
   * {@link #FRESH_VALUE} thereafter.
   */
  private static final class RewindableFunction implements SkyFunction {
    static final StringValue STALE_VALUE = new StringValue("stale");
    static final StringValue FRESH_VALUE = new StringValue("fresh");

    private int calls = 0;

    @Override
    public SkyValue compute(SkyKey skyKey, Environment env) {
      return ++calls == 1 ? STALE_VALUE : FRESH_VALUE;
    }
  }

  /**
   * The same dep is requested in two groups, but its value determines what the other dep in the
   * second group is. When it changes, the other dep in the second group should not be requested.
   */
  @Test
  public void sameDepInTwoGroups() throws Exception {
    initializeTester();

    // leaf4 should not be built in the second build.
    SkyKey leaf4 = skyKey("leaf4");
    AtomicBoolean shouldNotBuildLeaf4 = new AtomicBoolean(false);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (shouldNotBuildLeaf4.get()
              && key.equals(leaf4)
              && type != EventType.REMOVE_REVERSE_DEP
              && type != EventType.GET_BATCH) {
            throw new IllegalStateException(
                "leaf4 should not have been considered this build: "
                    + type
                    + ", "
                    + order
                    + ", "
                    + context);
          }
        },
        /* deterministic= */ false);
    tester.set(leaf4, new StringValue("leaf4"));

    // Create leaf0, leaf1 and leaf2 values with values "leaf2", "leaf3", "leaf4" respectively.
    // These will be requested as one dependency group. In the second build, leaf2 will have the
    // value "leaf5".
    List<SkyKey> leaves = new ArrayList<>();
    for (int i = 0; i <= 2; i++) {
      SkyKey leaf = i == 2 ? nonHermeticKey("leaf" + i) : skyKey("leaf" + i);
      leaves.add(leaf);
      tester.set(leaf, new StringValue("leaf" + (i + 2)));
    }

    // Create "top" value. It depends on all leaf values in two overlapping dependency groups.
    SkyKey topKey = skyKey("top");
    SkyValue topValue = new StringValue("top");
    tester
        .getOrCreate(topKey)
        .setBuilder(
            (skyKey, env) -> {
              // Request the first group, [leaf0, leaf1, leaf2].
              // In the first build, it has values ["leaf2", "leaf3", "leaf4"].
              // In the second build it has values ["leaf2", "leaf3", "leaf5"]
              SkyframeLookupResult values = env.getValuesAndExceptions(leaves);
              if (env.valuesMissing()) {
                return null;
              }

              // Request the second group. In the first build it's [leaf2, leaf4].
              // In the second build it's [leaf2, leaf5]
              env.getValuesAndExceptions(
                  ImmutableList.of(
                      leaves.get(2), skyKey(((StringValue) values.get(leaves.get(2))).getValue())));
              if (env.valuesMissing()) {
                return null;
              }

              return topValue;
            });

    // First build: assert we can evaluate "top".
    assertThat(tester.evalAndGet(/*keepGoing=*/ false, topKey)).isEqualTo(topValue);

    // Second build: replace "leaf4" by "leaf5" in leaf2's value. Assert leaf4 is not requested.
    SkyKey leaf5 = skyKey("leaf5");
    tester.set(leaf5, new StringValue("leaf5"));
    tester.set(leaves.get(2), new StringValue("leaf5"));
    tester.invalidate();
    shouldNotBuildLeaf4.set(true);
    assertThat(tester.evalAndGet(/*keepGoing=*/ false, topKey)).isEqualTo(topValue);
  }

  @Test
  public void dirtyAndChanged() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey mid = nonHermeticKey("mid");
    SkyKey top = skyKey("top");
    tester.getOrCreate(top).addDependency(mid).setComputedValue(COPY);
    tester.getOrCreate(mid).addDependency(leaf).setComputedValue(COPY);
    tester.set(leaf, new StringValue("leafy"));
    // For invalidation.
    tester.set("dummy", new StringValue("dummy"));
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("leafy");
    tester.set(leaf, new StringValue("crunchy"));
    tester.invalidate();
    // For invalidation.
    tester.evalAndGet("dummy");
    tester.getOrCreate(mid, /*markAsModified=*/ true);
    tester.invalidate();
    topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("crunchy");
  }

  /**
   * Test whether a value that was already marked changed will be incorrectly marked dirty, not
   * changed, if another thread tries to mark it just dirty. To exercise this, we need to have a
   * race condition where both threads see that the value is not dirty yet, then the "changed"
   * thread marks the value changed before the "dirty" thread marks the value dirty. To accomplish
   * this, we use a countdown latch to make the "dirty" thread wait until the "changed" thread is
   * done, and another countdown latch to make both of them wait until they have both checked if the
   * value is currently clean.
   */
  @Test
  public void dirtyAndChangedValueIsChanged() throws Exception {
    SkyKey parent = nonHermeticKey("parent");
    AtomicBoolean blockingEnabled = new AtomicBoolean(false);
    CountDownLatch waitForChanged = new CountDownLatch(1);
    // changed thread checks value entry once (to see if it is changed). dirty thread checks twice,
    // to see if it is changed, and if it is dirty.
    CountDownLatch threadsStarted = new CountDownLatch(3);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (!blockingEnabled.get()) {
            return;
          }
          if (!key.equals(parent)) {
            return;
          }
          if (type == EventType.IS_CHANGED && order == Order.BEFORE) {
            threadsStarted.countDown();
          }
          // Dirtiness only checked by dirty thread.
          if (type == EventType.IS_DIRTY && order == Order.BEFORE) {
            threadsStarted.countDown();
          }
          if (type == EventType.MARK_DIRTY) {
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                threadsStarted, "Both threads did not query if value isChanged in time");
            if (order == Order.BEFORE) {
              DirtyType dirtyType = (DirtyType) context;
              if (dirtyType.equals(DirtyType.DIRTY)) {
                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                    waitForChanged, "'changed' thread did not mark value changed in time");
                return;
              }
            }
            if (order == Order.AFTER) {
              DirtyType dirtyType = ((NotifyingHelper.MarkDirtyAfterContext) context).dirtyType();
              if (dirtyType.equals(DirtyType.CHANGE)) {
                waitForChanged.countDown();
              }
            }
          }
        },
        /* deterministic= */ false);
    SkyKey leaf = nonHermeticKey("leaf");
    tester.set(leaf, new StringValue("leaf"));
    tester.getOrCreate(parent).addDependency(leaf).setComputedValue(CONCATENATE);
    EvaluationResult<StringValue> result;
    result = tester.eval(/* keepGoing= */ false, parent);
    assertThat(result.get(parent).getValue()).isEqualTo("leaf");
    // Invalidate leaf, but don't actually change it. It will transitively dirty parent
    // concurrently with parent directly dirtying itself.
    tester.getOrCreate(leaf, /* markAsModified= */ true);
    SkyKey other2 = skyKey("other2");
    tester.set(other2, new StringValue("other2"));
    // Invalidate parent, actually changing it.
    tester.getOrCreate(parent, /* markAsModified= */ true).addDependency(other2);
    tester.invalidate();
    blockingEnabled.set(true);
    result = tester.eval(/* keepGoing= */ false, parent);
    assertThat(result.get(parent).getValue()).isEqualTo("leafother2");
    assertThat(waitForChanged.getCount()).isEqualTo(0);
    assertThat(threadsStarted.getCount()).isEqualTo(0);
  }

  @Test
  public void hermeticSkyFunctionCanThrowTransientErrorThenRecover() throws Exception {
    SkyKey leaf = skyKey("leaf");
    SkyKey top = skyKey("top");
    // When top depends on leaf, but throws a transient error,
    tester
        .getOrCreate(top)
        .addDependency(leaf)
        .setHasTransientError(true)
        .setComputedValue(CONCATENATE);
    StringValue value = new StringValue("value");
    tester.getOrCreate(leaf).setConstantValue(value);
    // And the first build throws a transient error (as expected),
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ true, top);
    assertThatEvaluationResult(result).hasError();
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(top).hasExceptionThat().isNotNull();
    // And then top's transient error is removed,
    tester.getOrCreate(top, /*markAsModified=*/ false).setHasTransientError(false);
    tester.invalidateTransientErrors();
    // Then top evaluates successfully, even though it was hermetic and didn't give the same result
    // on successive evaluations with the same inputs.
    result = tester.eval(/*keepGoing=*/ true, top);
    assertThatEvaluationResult(result).hasNoError();
    assertThatEvaluationResult(result).hasEntryThat(top).isEqualTo(value);
  }

  @Test
  public void singleValueDependsOnManyDirtyValues() throws Exception {
    SkyKey[] values = new SkyKey[TEST_NODE_COUNT];
    StringBuilder expected = new StringBuilder();
    for (int i = 0; i < values.length; i++) {
      String valueName = Integer.toString(i);
      values[i] = nonHermeticKey(valueName);
      tester.set(values[i], new StringValue(valueName));
      expected.append(valueName);
    }
    SkyKey topKey = skyKey("top");
    TestFunction value = tester.getOrCreate(topKey).setComputedValue(CONCATENATE);
    for (SkyKey skyKey : values) {
      value.addDependency(skyKey);
    }

    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, topKey);
    assertThat(result.get(topKey)).isEqualTo(new StringValue(expected.toString()));

    for (int j = 0; j < RUNS; j++) {
      for (SkyKey skyKey : values) {
        tester.getOrCreate(skyKey, /*markAsModified=*/ true);
      }
      // This value has an error, but we should never discover it because it is not marked changed
      // and all of its dependencies re-evaluate to the same thing.
      tester.getOrCreate(topKey, /*markAsModified=*/ false).setHasError(true);
      tester.invalidate();

      result = tester.eval(/* keepGoing= */ false, topKey);
      assertThat(result.get(topKey)).isEqualTo(new StringValue(expected.toString()));
    }
  }

  /**
   * Tests scenario where we have dirty values in the graph, and then one of them is deleted since
   * its evaluation did not complete before an error was thrown. Can either test the graph via an
   * evaluation of that deleted value, or an invalidation of a child, and can either remove the
   * thrown error or throw it again on that evaluation.
   */
  private void dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort(
      boolean reevaluateMissingValue, boolean removeError) throws Exception {
    SkyKey errorKey = nonHermeticKey("error");
    tester.set(errorKey, new StringValue("biding time"));
    SkyKey slowKey = nonHermeticKey("slow");
    tester.set(slowKey, new StringValue("slow"));
    SkyKey midKey = skyKey("mid");
    tester.getOrCreate(midKey).addDependency(slowKey).setComputedValue(COPY);
    SkyKey lastKey = nonHermeticKey("last");
    tester.set(lastKey, new StringValue("last"));
    SkyKey motherKey = skyKey("mother");
    tester
        .getOrCreate(motherKey)
        .addDependency(errorKey)
        .addDependency(midKey)
        .addDependency(lastKey)
        .setComputedValue(CONCATENATE);
    SkyKey fatherKey = skyKey("father");
    tester
        .getOrCreate(fatherKey)
        .addDependency(errorKey)
        .addDependency(midKey)
        .addDependency(lastKey)
        .setComputedValue(CONCATENATE);
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, motherKey, fatherKey);
    assertThat(result.get(motherKey).getValue()).isEqualTo("biding timeslowlast");
    assertThat(result.get(fatherKey).getValue()).isEqualTo("biding timeslowlast");
    tester.set(slowKey, null);
    // Each parent depends on errorKey, midKey, lastKey. We keep slowKey waiting until errorKey is
    // finished. So there is no way lastKey can be enqueued by either parent. Thus, the parent that
    // is cleaned has not interacted with lastKey this build. Still, lastKey's reverse dep on that
    // parent should be removed.
    CountDownLatch errorFinish = new CountDownLatch(1);
    tester.set(errorKey, null);
    tester
        .getOrCreate(errorKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ null,
                /*waitToFinish=*/ null,
                /*notifyFinish=*/ errorFinish,
                /*waitForException=*/ false,
                /*value=*/ null,
                /*deps=*/ ImmutableList.of()));
    tester
        .getOrCreate(slowKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ null,
                /*waitToFinish=*/ errorFinish,
                /*notifyFinish=*/ null,
                /*waitForException=*/ true,
                new StringValue("leaf2"),
                /*deps=*/ ImmutableList.of()));
    tester.invalidate();
    // errorKey finishes, written to graph -> leafKey maybe starts+finishes & (Visitor aborts)
    // -> one of mother or father builds. The other one should be cleaned, and no references to it
    // left in the graph.
    result = tester.eval(/*keepGoing=*/ false, motherKey, fatherKey);
    assertThat(result.hasError()).isTrue();
    // Only one of mother or father should be in the graph.
    assertWithMessage(result.getError(motherKey) + ", " + result.getError(fatherKey))
        .that((result.getError(motherKey) == null) != (result.getError(fatherKey) == null))
        .isTrue();
    SkyKey parentKey =
        (reevaluateMissingValue == (result.getError(motherKey) == null)) ? motherKey : fatherKey;
    // Give slowKey a nice ordinary builder.
    tester
        .getOrCreate(slowKey, /*markAsModified=*/ false)
        .setBuilder(null)
        .setConstantValue(new StringValue("leaf2"));
    if (removeError) {
      tester
          .getOrCreate(errorKey, /*markAsModified=*/ true)
          .setBuilder(null)
          .setConstantValue(new StringValue("reformed"));
    }
    String lastString = "last";
    if (!reevaluateMissingValue) {
      // Mark the last key modified if we're not trying the absent value again. This invalidation
      // will test if lastKey still has a reference to the absent value.
      lastString = "last2";
      tester.set(lastKey, new StringValue(lastString));
    }
    tester.invalidate();
    result = tester.eval(/*keepGoing=*/ false, parentKey);
    if (removeError) {
      assertThat(result.get(parentKey).getValue()).isEqualTo("reformedleaf2" + lastString);
    } else {
      assertThat(result.getError(parentKey)).isNotNull();
    }
  }

  /**
   * The following four tests (dirtyChildrenProperlyRemovedWith*) test the consistency of the graph
   * after a failed build in which a dirty value should have been deleted from the graph. The
   * consistency is tested via either evaluating the missing value, or the re-evaluating the present
   * value, and either clearing the error or keeping it. To evaluate the present value, we
   * invalidate the error value to force re-evaluation. Related to bug "skyframe m1: graph may not
   * be properly cleaned on interrupt or failure".
   */
  @Test
  public void dirtyChildrenProperlyRemovedWithInvalidateRemoveError() throws Exception {
    dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort(
        /*reevaluateMissingValue=*/ false, /*removeError=*/ true);
  }

  @Test
  public void dirtyChildrenProperlyRemovedWithInvalidateKeepError() throws Exception {
    dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort(
        /*reevaluateMissingValue=*/ false, /*removeError=*/ false);
  }

  @Test
  public void dirtyChildrenProperlyRemovedWithReevaluateRemoveError() throws Exception {
    dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort(
        /*reevaluateMissingValue=*/ true, /*removeError=*/ true);
  }

  @Test
  public void dirtyChildrenProperlyRemovedWithReevaluateKeepError() throws Exception {
    dirtyValueChildrenProperlyRemovedOnEarlyBuildAbort(
        /*reevaluateMissingValue=*/ true, /*removeError=*/ false);
  }

  /**
   * Regression test: enqueue so many values that some of them won't have started processing, and
   * then either interrupt processing or have a child throw an error. In the latter case, this also
   * tests that a value that hasn't started processing can still have a child error bubble up to it.
   * In both cases, it tests that the graph is properly cleaned of the dirty values and references
   * to them.
   */
  private void manyDirtyValuesClearChildrenOnFail(boolean interrupt) throws Exception {
    SkyKey leafKey = nonHermeticKey("leaf");
    tester.set(leafKey, new StringValue("leafy"));
    SkyKey lastKey = nonHermeticKey("last");
    tester.set(lastKey, new StringValue("last"));
    List<SkyKey> tops = new ArrayList<>();
    // Request far more top-level values than there are threads, so some of them will block until
    // the
    // leaf child is enqueued for processing.
    for (int i = 0; i < 10000; i++) {
      SkyKey topKey = skyKey("top" + i);
      tester
          .getOrCreate(topKey)
          .addDependency(leafKey)
          .addDependency(lastKey)
          .setComputedValue(CONCATENATE);
      tops.add(topKey);
    }
    tester.eval(/*keepGoing=*/ false, tops.toArray(new SkyKey[0]));
    CountDownLatch notifyStart = new CountDownLatch(1);
    tester.set(leafKey, null);
    if (interrupt) {
      // leaf will wait for an interrupt if desired. We cannot use the usual ChainedFunction
      // because we need to actually throw the interrupt.
      AtomicBoolean shouldSleep = new AtomicBoolean(true);
      tester
          .getOrCreate(leafKey, /*markAsModified=*/ true)
          .setBuilder(
              (skyKey, env) -> {
                notifyStart.countDown();
                if (shouldSleep.get()) {
                  // Should be interrupted within 5 seconds.
                  Thread.sleep(5000);
                  throw new AssertionError("leaf was not interrupted");
                }
                return new StringValue("crunchy");
              });
      tester.invalidate();
      TestThread evalThread =
          new TestThread(
              () ->
                  assertThrows(
                      InterruptedException.class,
                      () -> tester.eval(/*keepGoing=*/ false, tops.toArray(new SkyKey[0]))));
      evalThread.start();
      assertThat(notifyStart.await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS)).isTrue();
      evalThread.interrupt();
      evalThread.joinAndAssertState(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
      // Free leafKey to compute next time.
      shouldSleep.set(false);
    } else {
      // Non-interrupt case. Just throw an error in the child.
      tester.getOrCreate(leafKey, /*markAsModified=*/ true).setHasError(true);
      tester.invalidate();
      // The error thrown may non-deterministically bubble up to a parent that has not yet started
      // processing, but has been enqueued for processing.
      tester.eval(/*keepGoing=*/ false, tops.toArray(new SkyKey[0]));
      tester.getOrCreate(leafKey, /*markAsModified=*/ true).setHasError(false);
      tester.set(leafKey, new StringValue("crunchy"));
    }
    // lastKey was not touched during the previous build, but its reverse deps on its parents should
    // still be accurate.
    tester.set(lastKey, new StringValue("new last"));
    tester.invalidate();
    EvaluationResult<StringValue> result =
        tester.eval(/*keepGoing=*/ false, tops.toArray(new SkyKey[0]));
    for (SkyKey topKey : tops) {
      assertWithMessage(topKey.toString())
          .that(result.get(topKey).getValue())
          .isEqualTo("crunchynew last");
    }
  }

  /**
   * Regression test: make sure that if an evaluation fails before a dirty value starts evaluation
   * (in particular, before it is reset), the graph remains consistent.
   */
  @Test
  public void manyDirtyValuesClearChildrenOnError() throws Exception {
    manyDirtyValuesClearChildrenOnFail(/*interrupt=*/ false);
  }

  /**
   * Regression test: Make sure that if an evaluation is interrupted before a dirty value starts
   * evaluation (in particular, before it is reset), the graph remains consistent.
   */
  @Test
  public void manyDirtyValuesClearChildrenOnInterrupt() throws Exception {
    manyDirtyValuesClearChildrenOnFail(/*interrupt=*/ true);
  }

  private SkyKey makeTestKey(SkyKey node0) {
    SkyKey key = null;
    // Create a long chain of nodes. Most of them will not actually be dirtied, but the last one to
    // be dirtied will enqueue its parent for dirtying, so it will be in the queue for the next run.
    for (int i = 0; i < TEST_NODE_COUNT; i++) {
      key = i == 0 ? node0 : skyKey("node" + i);
      if (i > 1) {
        tester.getOrCreate(key).addDependency("node" + (i - 1)).setComputedValue(COPY);
      } else if (i == 1) {
        tester.getOrCreate(key).addDependency(node0).setComputedValue(COPY);
      } else {
        tester.set(key, new StringValue("node0"));
      }
    }
    return key;
  }

  /**
   * Regression test for case where the user requests that we delete nodes that are already in the
   * queue to be dirtied. We should handle that gracefully and not complain.
   */
  @Test
  public void deletingDirtyNodes() throws Exception {
    SkyKey node0 = nonHermeticKey("node0");
    SkyKey key = makeTestKey(node0);
    // Seed the graph.
    assertThat(((StringValue) tester.evalAndGet(/*keepGoing=*/ false, key)).getValue())
        .isEqualTo("node0");
    // Start the dirtying process.
    tester.set(node0, new StringValue("new"));
    tester.invalidate();

    // Interrupt current thread on a next invalidate call
    Thread thread = Thread.currentThread();
    tester.progressReceiver.setNextInvalidationCallback(thread::interrupt);

    assertThrows(InterruptedException.class, () -> tester.eval(/*keepGoing=*/ false, key));

    // Cleanup + paranoid check
    tester.progressReceiver.setNextInvalidationCallback(null);
    // Now delete all the nodes. The node that was going to be dirtied is also deleted, which we
    // should handle.
    tester.evaluator.delete(Predicates.alwaysTrue());
    assertThat(((StringValue) tester.evalAndGet(/*keepGoing=*/ false, key)).getValue())
        .isEqualTo("new");
  }

  @Test
  public void changePruning() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey mid = skyKey("mid");
    SkyKey top = skyKey("top");
    tester.getOrCreate(top).addDependency(mid).setComputedValue(COPY);
    tester.getOrCreate(mid).addDependency(leaf).setComputedValue(COPY);
    tester.set(leaf, new StringValue("leafy"));
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("leafy");
    // Mark leaf changed, but don't actually change it.
    tester.getOrCreate(leaf, /* markAsModified= */ true);
    // mid will give an error if re-evaluated, but it shouldn't be because it is not marked changed,
    // and its dirty child will evaluate to the same element.
    tester.getOrCreate(mid, /* markAsModified= */ false).setHasError(true);
    tester.invalidate();
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, top);
    assertThat(result.hasError()).isFalse();
    topValue = result.get(top);
    assertThat(topValue.getValue()).isEqualTo("leafy");
    assertThat(tester.getDirtyKeys()).isEmpty();
    assertThat(tester.getDeletedKeys()).isEmpty();
  }

  @Test
  public void changePruningWithDoneValue() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey mid = skyKey("mid");
    SkyKey top = skyKey("top");
    SkyKey suffix = skyKey("suffix");
    StringValue suffixValue = new StringValue("suffix");
    tester.set(suffix, suffixValue);
    tester.getOrCreate(top).addDependency(mid).addDependency(suffix).setComputedValue(CONCATENATE);
    tester.getOrCreate(mid).addDependency(leaf).addDependency(suffix).setComputedValue(CONCATENATE);
    SkyValue leafyValue = new StringValue("leafy");
    tester.set(leaf, leafyValue);
    StringValue value = (StringValue) tester.evalAndGet("top");
    assertThat(value.getValue()).isEqualTo("leafysuffixsuffix");
    // Mark leaf changed, but don't actually change it.
    tester.getOrCreate(leaf, /* markAsModified= */ true);
    // mid will give an error if re-evaluated, but it shouldn't be because it is not marked changed,
    // and its dirty child will evaluate to the same element.
    tester.getOrCreate(mid, /*markAsModified=*/ false).setHasError(true);
    tester.invalidate();
    value = (StringValue) tester.evalAndGet(/*keepGoing=*/ false, leaf);
    assertThat(value.getValue()).isEqualTo("leafy");
    assertThat(tester.getDirtyKeys()).containsExactly(mid, top);
    assertThat(tester.getDeletedKeys()).isEmpty();
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, top);
    assertWithMessage(result.toString()).that(result.hasError()).isFalse();
    value = result.get(top);
    assertThat(value.getValue()).isEqualTo("leafysuffixsuffix");
    assertThat(tester.getDirtyKeys()).isEmpty();
    assertThat(tester.getDeletedKeys()).isEmpty();
  }

  @Test
  public void changePruningAfterParentPrunes() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey top = skyKey("top");
    tester.set(leaf, new StringValue("leafy"));
    // When top depends on leaf, but always returns the same value,
    StringValue fixedTopValue = new StringValue("top");
    AtomicBoolean topEvaluated = new AtomicBoolean(false);
    tester
        .getOrCreate(top)
        .setBuilder(
            (skyKey, env) -> {
              topEvaluated.set(true);
              return env.getValue(leaf) == null ? null : fixedTopValue;
            });
    // And top is evaluated,
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    // Then top's value is as expected,
    assertThat(topValue).isEqualTo(fixedTopValue);
    // And top was actually evaluated.
    assertThat(topEvaluated.get()).isTrue();
    // When leaf is changed,
    tester.set(leaf, new StringValue("crunchy"));
    tester.invalidate();
    topEvaluated.set(false);
    // And top is evaluated,
    StringValue topValue2 = (StringValue) tester.evalAndGet("top");
    // Then top's value is as expected,
    assertThat(topValue2).isEqualTo(fixedTopValue);
    // And top was actually evaluated.
    assertThat(topEvaluated.get()).isTrue();
    // When leaf is invalidated but not actually changed,
    tester.getOrCreate(leaf, /*markAsModified=*/ true);
    tester.invalidate();
    topEvaluated.set(false);
    // And top is evaluated,
    StringValue topValue3 = (StringValue) tester.evalAndGet("top");
    // Then top's value is as expected,
    assertThat(topValue3).isEqualTo(fixedTopValue);
    // And top was *not* actually evaluated, because change pruning cut off evaluation.
    assertThat(topEvaluated.get()).isFalse();
  }

  @Test
  public void changePruningFromOtherNodeAfterParentPrunes() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey other = nonHermeticKey("other");
    SkyKey top = skyKey("top");
    tester.set(leaf, new StringValue("leafy"));
    tester.set(other, new StringValue("other"));
    // When top depends on leaf and other, but always returns the same value,
    StringValue fixedTopValue = new StringValue("top");
    AtomicBoolean topEvaluated = new AtomicBoolean(false);
    tester
        .getOrCreate(top)
        .setBuilder(
            (skyKey, env) -> {
              topEvaluated.set(true);

              return env.getValue(other) == null || env.getValue(leaf) == null
                  ? null
                  : fixedTopValue;
            });
    // And top is evaluated,
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    // Then top's value is as expected,
    assertThat(topValue).isEqualTo(fixedTopValue);
    // And top was actually evaluated.
    assertThat(topEvaluated.get()).isTrue();
    // When leaf is changed,
    tester.set(leaf, new StringValue("crunchy"));
    tester.invalidate();
    topEvaluated.set(false);
    // And top is evaluated,
    StringValue topValue2 = (StringValue) tester.evalAndGet("top");
    // Then top's value is as expected,
    assertThat(topValue2).isEqualTo(fixedTopValue);
    // And top was actually evaluated.
    assertThat(topEvaluated.get()).isTrue();
    // When other is invalidated but not actually changed,
    tester.getOrCreate(other, /*markAsModified=*/ true);
    tester.invalidate();
    topEvaluated.set(false);
    // And top is evaluated,
    StringValue topValue3 = (StringValue) tester.evalAndGet("top");
    // Then top's value is as expected,
    assertThat(topValue3).isEqualTo(fixedTopValue);
    // And top was *not* actually evaluated, because change pruning cut off evaluation.
    assertThat(topEvaluated.get()).isFalse();
  }

  @Test
  public void changedChildChangesDepOfParent() throws Exception {
    SkyKey buildFile = nonHermeticKey("buildFile");
    ValueComputer authorDrink =
        (deps, env) -> {
          String author = ((StringValue) deps.get(buildFile)).getValue();
          StringValue beverage;
          switch (author) {
            case "hemingway":
              beverage = (StringValue) env.getValue(skyKey("absinthe"));
              break;
            case "joyce":
              beverage = (StringValue) env.getValue(skyKey("whiskey"));
              break;
            default:
              throw new IllegalStateException(author);
          }
          if (beverage == null) {
            return null;
          }
          return new StringValue(author + " drank " + beverage.getValue());
        };

    tester.set(buildFile, new StringValue("hemingway"));
    SkyKey absinthe = skyKey("absinthe");
    tester.set(absinthe, new StringValue("absinthe"));
    SkyKey whiskey = skyKey("whiskey");
    tester.set(whiskey, new StringValue("whiskey"));
    SkyKey top = skyKey("top");
    tester.getOrCreate(top).addDependency(buildFile).setComputedValue(authorDrink);
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("hemingway drank absinthe");
    tester.set(buildFile, new StringValue("joyce"));
    // Don't evaluate absinthe successfully anymore.
    tester.getOrCreate(absinthe, /*markAsModified=*/ false).setHasError(true);
    tester.invalidate();
    topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("joyce drank whiskey");
      assertThat(tester.getDirtyKeys()).containsExactly(buildFile, top);
      assertThat(tester.getDeletedKeys()).isEmpty();
  }

  @Test
  public void dirtyDepIgnoresChildren() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey mid = skyKey("mid");
    SkyKey top = skyKey("top");
    tester.set(mid, new StringValue("ignore"));
    tester.getOrCreate(top).addDependency(mid).setComputedValue(COPY);
    tester.getOrCreate(mid).addDependency(leaf);
    tester.set(leaf, new StringValue("leafy"));
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("ignore");
    assertThat(tester.getDirtyKeys()).isEmpty();
    assertThat(tester.getDeletedKeys()).isEmpty();
    // Change leaf.
    tester.set(leaf, new StringValue("crunchy"));
    tester.invalidate();
    topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("ignore");
      assertThat(tester.getDirtyKeys()).containsExactly(leaf);
      assertThat(tester.getDeletedKeys()).isEmpty();
    tester.set(leaf, new StringValue("smushy"));
    tester.invalidate();
    topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("ignore");
      assertThat(tester.getDirtyKeys()).containsExactly(leaf);
      assertThat(tester.getDeletedKeys()).isEmpty();
  }

  private static final SkyFunction INTERRUPT_BUILDER =
      (skyKey, env) -> {
        throw new InterruptedException();
      };

  /**
   * Utility function to induce a graph clean of whatever value is requested, by trying to build
   * this value and interrupting the build as soon as this value's function evaluation starts.
   */
  private void failBuildAndRemoveValue(SkyKey value) throws InterruptedException {
    tester.set(value, null);
    // Evaluator will think leaf was interrupted because it threw, so it will be cleaned from graph.
    tester.getOrCreate(value, /* markAsModified= */ true).setBuilder(INTERRUPT_BUILDER);
    tester.invalidate();
    assertThrows(InterruptedException.class, () -> tester.eval(/* keepGoing= */ false, value));
    tester.getOrCreate(value, /* markAsModified= */ false).setBuilder(null);
  }

  /**
   * Make sure that when a dirty value is building, the fact that a child may no longer exist in the
   * graph doesn't cause problems.
   */
  @Test
  public void dirtyBuildAfterFailedBuild() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey top = skyKey("top");
    tester.getOrCreate(top).addDependency(leaf).setComputedValue(COPY);
    tester.set(leaf, new StringValue("leafy"));
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("leafy");
    assertThat(tester.getDirtyKeys()).isEmpty();
    assertThat(tester.getDeletedKeys()).isEmpty();
    failBuildAndRemoveValue(leaf);
    // Leaf should no longer exist in the graph. Check that this doesn't cause problems.
    tester.set(leaf, null);
    tester.set(leaf, new StringValue("crunchy"));
    tester.invalidate();
    topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("crunchy");
  }

  /**
   * Regression test: error when clearing reverse deps on dirty value about to be rebuilt, because
   * child values were deleted and recreated in interim, forgetting they had reverse dep on dirty
   * value in the first place.
   */
  @Test
  public void changedBuildAfterFailedThenSuccessfulBuild() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey top = nonHermeticKey("top");
    tester.getOrCreate(top).addDependency(leaf).setComputedValue(COPY);
    tester.set(leaf, new StringValue("leafy"));
    StringValue topValue = (StringValue) tester.evalAndGet(/* keepGoing= */ false, top);
    assertThat(topValue.getValue()).isEqualTo("leafy");
    assertThat(tester.getDirtyKeys()).isEmpty();
    assertThat(tester.getDeletedKeys()).isEmpty();
    failBuildAndRemoveValue(leaf);
    tester.set(leaf, new StringValue("crunchy"));
    tester.invalidate();
    tester.eval(/* keepGoing= */ false, leaf);
    // Leaf no longer has reverse dep on top. Check that this doesn't cause problems, even if the
    // top value is evaluated unconditionally.
    tester.getOrCreate(top, /*markAsModified=*/ true);
    tester.invalidate();
    topValue = (StringValue) tester.evalAndGet(/*keepGoing=*/ false, top);
    assertThat(topValue.getValue()).isEqualTo("crunchy");
  }

  /**
   * Regression test: child value that has been deleted since it and its parent were marked dirty no
   * longer knows it has a reverse dep on its parent.
   *
   * <p>Start with:
   *
   * <pre>
   *              top0  ... top1000
   *                  \  | /
   *                   leaf
   * </pre>
   *
   * Then fail to build leaf. Now the entry for leaf should have no "memory" that it was ever
   * depended on by tops. Now build tops, but fail again.
   */
  @Test
  public void manyDirtyValuesClearChildrenOnSecondFail() throws Exception {
    SkyKey leafKey = nonHermeticKey("leaf");
    tester.set(leafKey, new StringValue("leafy"));
    SkyKey lastKey = skyKey("last");
    tester.set(lastKey, new StringValue("last"));
    List<SkyKey> tops = new ArrayList<>();
    // Request far more top-level values than there are threads, so some of them will block until
    // the leaf child is enqueued for processing.
    for (int i = 0; i < 10000; i++) {
      SkyKey topKey = skyKey("top" + i);
      tester
          .getOrCreate(topKey)
          .addDependency(leafKey)
          .addDependency(lastKey)
          .setComputedValue(CONCATENATE);
      tops.add(topKey);
    }
    tester.eval(/*keepGoing=*/ false, tops.toArray(new SkyKey[0]));
    failBuildAndRemoveValue(leafKey);
    // Request the tops. Since leaf was deleted from the graph last build, it no longer knows that
    // its parents depend on it. When leaf throws, at least one of its parents (hopefully) will not
    // have re-informed leaf that the parent depends on it, exposing the bug, since the parent
    // should then not try to clean the reverse dep from leaf.
    tester.set(leafKey, null);
    // Evaluator will think leaf was interrupted because it threw, so it will be cleaned from graph.
    tester.getOrCreate(leafKey, /*markAsModified=*/ true).setBuilder(INTERRUPT_BUILDER);
    tester.invalidate();
    assertThrows(
        InterruptedException.class,
        () -> tester.eval(/*keepGoing=*/ false, tops.toArray(new SkyKey[0])));
  }

  @Test
  public void failedDirtyBuild() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey top = skyKey("top");
    tester
        .getOrCreate(top)
        .addErrorDependency(leaf, new StringValue("recover"))
        .setComputedValue(COPY);
    tester.set(leaf, new StringValue("leafy"));
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("leafy");
    assertThat(tester.getDirtyKeys()).isEmpty();
    assertThat(tester.getDeletedKeys()).isEmpty();
    // Change leaf.
    tester.getOrCreate(leaf, /* markAsModified= */ true).setHasError(true);
    tester.getOrCreate(top, /* markAsModified= */ false).setHasError(true);
    tester.invalidate();
    EvaluationResult<StringValue> result = tester.eval(/* keepGoing= */ false, top);
    assertThatEvaluationResult(result).hasSingletonErrorThat(top);
  }

  @Test
  public void failedDirtyBuildInBuilder() throws Exception {
    SkyKey leaf = nonHermeticKey("leaf");
    SkyKey secondError = nonHermeticKey("secondError");
    SkyKey top = skyKey("top");
    tester
        .getOrCreate(top)
        .addDependency(leaf)
        .addErrorDependency(secondError, new StringValue("recover"))
        .setComputedValue(CONCATENATE);
    tester.set(secondError, new StringValue("secondError")).addDependency(leaf);
    tester.set(leaf, new StringValue("leafy"));
    StringValue topValue = (StringValue) tester.evalAndGet("top");
    assertThat(topValue.getValue()).isEqualTo("leafysecondError");
    assertThat(tester.getDirtyKeys()).isEmpty();
    assertThat(tester.getDeletedKeys()).isEmpty();
    // Invalidate leaf.
    tester.getOrCreate(leaf, /*markAsModified=*/ true);
    tester.set(leaf, new StringValue("crunchy"));
    tester.getOrCreate(secondError, /*markAsModified=*/ true).setHasError(true);
    tester.getOrCreate(top, /*markAsModified=*/ false).setHasError(true);
    tester.invalidate();
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, top);
    assertThatEvaluationResult(result).hasSingletonErrorThat(top);
  }

  @Test
  public void dirtyErrorTransienceValue() throws Exception {
    initializeTester();
    SkyKey error = skyKey("error");
    tester.getOrCreate(error).setHasError(true);
    assertThat(tester.evalAndGetError(/*keepGoing=*/ true, error)).isNotNull();
    tester.invalidateTransientErrors();
    SkyKey secondError = skyKey("secondError");
    tester.getOrCreate(secondError).setHasError(true);
    // secondError declares a new dependence on ErrorTransienceValue, but not until it has already
    // thrown an error.
    assertThat(tester.evalAndGetError(/*keepGoing=*/ true, secondError)).isNotNull();
  }

  @Test
  public void dirtyDependsOnErrorTurningGood() throws Exception {
    SkyKey error = nonHermeticKey("error");
    tester.getOrCreate(error).setHasError(true);
    SkyKey topKey = skyKey("top");
    tester.getOrCreate(topKey).addDependency(error).setComputedValue(COPY);
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, topKey);
    assertThatEvaluationResult(result).hasSingletonErrorThat(topKey);
    tester.getOrCreate(error).setHasError(false);
    StringValue val = new StringValue("reformed");
    tester.set(error, val);
    tester.invalidate();
    result = tester.eval(/*keepGoing=*/ false, topKey);
    assertThatEvaluationResult(result).hasEntryThat(topKey).isEqualTo(val);
    assertThatEvaluationResult(result).hasNoError();
  }

  /** Regression test for crash bug. */
  @Test
  public void dirtyWithOwnErrorDependsOnTransientErrorTurningGood() throws Exception {
    SkyKey error = nonHermeticKey("error");
    tester.getOrCreate(error).setHasTransientError(true);
    SkyKey topKey = skyKey("top");
    SkyFunction errorFunction =
        (skyKey, env) -> {
          try {
            return env.getValueOrThrow(error, SomeErrorException.class);
          } catch (SomeErrorException e) {
            throw new GenericFunctionException(e, Transience.PERSISTENT);
          }
        };
    tester.getOrCreate(topKey).setBuilder(errorFunction);
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, topKey);
    tester.invalidateTransientErrors();
    assertThatEvaluationResult(result).hasSingletonErrorThat(topKey);
    tester.getOrCreate(error).setHasTransientError(false);
    StringValue reformed = new StringValue("reformed");
    tester.set(error, reformed);
    tester
        .getOrCreate(topKey, /*markAsModified=*/ false)
        .setBuilder(null)
        .addDependency(error)
        .setComputedValue(COPY);
    tester.invalidate();
    tester.invalidateTransientErrors();
    result = tester.eval(/*keepGoing=*/ false, topKey);
    assertThatEvaluationResult(result).hasEntryThat(topKey).isEqualTo(reformed);
    assertThatEvaluationResult(result).hasNoError();
  }

  /**
   * Make sure that when an error is thrown, it is given for handling only to parents that have
   * already registered a dependence on the value that threw the error.
   *
   * <pre>
   *  topBubbleKey  topErrorFirstKey
   *    |       \    /
   *  midKey  errorKey
   *    |
   * slowKey
   * </pre>
   *
   * On the second build, errorKey throws, and the threadpool aborts before midKey finishes.
   * topBubbleKey therefore has not yet requested errorKey this build. If errorKey bubbles up to it,
   * topBubbleKey must be able to handle that. (The evaluator can deal with this either by not
   * allowing errorKey to bubble up to topBubbleKey, or by dealing with that case.)
   */
  @Test
  public void errorOnlyBubblesToRequestingParents() throws Exception {
    // We need control over the order of reverse deps, so use a deterministic graph.
    makeGraphDeterministic();
    SkyKey errorKey = nonHermeticKey("error");
    tester.set(errorKey, new StringValue("biding time"));
    SkyKey slowKey = nonHermeticKey("slow");
    tester.set(slowKey, new StringValue("slow"));
    SkyKey midKey = skyKey("mid");
    tester.getOrCreate(midKey).addDependency(slowKey).setComputedValue(COPY);
    SkyKey topErrorFirstKey = skyKey("2nd top alphabetically");
    tester.getOrCreate(topErrorFirstKey).addDependency(errorKey).setComputedValue(CONCATENATE);
    SkyKey topBubbleKey = skyKey("1st top alphabetically");
    tester
        .getOrCreate(topBubbleKey)
        .addDependency(midKey)
        .addDependency(errorKey)
        .setComputedValue(CONCATENATE);
    // First error-free evaluation, to put all values in graph.
    EvaluationResult<StringValue> result =
        tester.eval(/*keepGoing=*/ false, topErrorFirstKey, topBubbleKey);
    assertThat(result.get(topErrorFirstKey).getValue()).isEqualTo("biding time");
    assertThat(result.get(topBubbleKey).getValue()).isEqualTo("slowbiding time");
    // Set up timing of child values: slowKey waits to finish until errorKey has thrown an
    // exception that has been caught by the threadpool.
    tester.set(slowKey, null);
    CountDownLatch errorFinish = new CountDownLatch(1);
    tester.set(errorKey, null);
    tester
        .getOrCreate(errorKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ null,
                /*waitToFinish=*/ null,
                /*notifyFinish=*/ errorFinish,
                /*waitForException=*/ false,
                /*value=*/ null,
                /*deps=*/ ImmutableList.of()));
    tester
        .getOrCreate(slowKey)
        .setBuilder(
            new ChainedFunction(
                /*notifyStart=*/ null,
                /*waitToFinish=*/ errorFinish,
                /*notifyFinish=*/ null,
                /*waitForException=*/ true,
                new StringValue("leaf2"),
                /*deps=*/ ImmutableList.of()));
    tester.invalidate();
    // errorKey finishes, written to graph -> slowKey maybe starts+finishes & (Visitor aborts)
    // -> some top key builds.
    result = tester.eval(/*keepGoing=*/ false, topErrorFirstKey, topBubbleKey);
    assertThat(result.hasError()).isTrue();
    assertWithMessage(result.toString()).that(result.getError(topErrorFirstKey)).isNotNull();
  }

  @Test
  public void dirtyWithRecoveryErrorDependsOnErrorTurningGood() throws Exception {
    SkyKey error = nonHermeticKey("error");
    tester.getOrCreate(error).setHasError(true);
    SkyKey topKey = skyKey("top");
    SkyFunction recoveryErrorFunction =
        (skyKey, env) -> {
          try {
            env.getValueOrThrow(error, SomeErrorException.class);
          } catch (SomeErrorException e) {
            throw new GenericFunctionException(e, Transience.PERSISTENT);
          }
          return null;
        };
    tester.getOrCreate(topKey).setBuilder(recoveryErrorFunction);
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, topKey);
    assertThatEvaluationResult(result).hasSingletonErrorThat(topKey);
    tester.getOrCreate(error).setHasError(false);
    StringValue reformed = new StringValue("reformed");
    tester.set(error, reformed);
    tester.getOrCreate(topKey).setBuilder(null).addDependency(error).setComputedValue(COPY);
    tester.invalidate();
    result = tester.eval(/*keepGoing=*/ false, topKey);
    assertThatEvaluationResult(result).hasEntryThat(topKey).isEqualTo(reformed);
    assertThatEvaluationResult(result).hasNoError();
  }

  /**
   * Similar to {@link ParallelEvaluatorTest#errorTwoLevelsDeep}, except here we request multiple
   * toplevel values.
   */
  @Test
  public void errorPropagationToTopLevelValues() throws Exception {
    SkyKey topKey = skyKey("top");
    SkyKey midKey = skyKey("mid");
    SkyKey badKey = skyKey("bad");
    tester.getOrCreate(topKey).addDependency(midKey).setComputedValue(CONCATENATE);
    tester.getOrCreate(midKey).addDependency(badKey).setComputedValue(CONCATENATE);
    tester.getOrCreate(badKey).setHasError(true);
    EvaluationResult<SkyValue> result = tester.eval(/* keepGoing= */ false, topKey, midKey);
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(midKey);
    // Do it again with keepGoing.  We should also see an error for the top key this time.
    result = tester.eval(/* keepGoing= */ true, topKey, midKey);
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(midKey);
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(topKey);
  }

  @Test
  public void breakWithInterruptibleErrorDep() throws Exception {
    SkyKey errorKey = skyKey("my_error_value");
    tester.getOrCreate(errorKey).setHasError(true);
    SkyKey parentKey = skyKey("parent");
    tester
        .getOrCreate(parentKey)
        .addErrorDependency(errorKey, new StringValue("recovered"))
        .setComputedValue(CONCATENATE);
    // When the error value throws, the propagation will cause an interrupted exception in parent.
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, parentKey);
    assertThat(result.keyNames()).isEmpty();
    assertThatEvaluationResult(result).hasErrorMapThat().hasSize(1);
    assertThatEvaluationResult(result).hasErrorMapThat().containsKey(parentKey);
    assertThat(Thread.interrupted()).isFalse();
    result = tester.eval(/*keepGoing=*/ true, parentKey);
    assertThatEvaluationResult(result).hasNoError();
    assertThatEvaluationResult(result)
        .hasEntryThat(parentKey)
        .isEqualTo(new StringValue("recovered"));
  }

  /**
   * Regression test: "clearing incomplete values on --keep_going build is racy". Tests that if a
   * value is requested on the first (non-keep-going) build and its child throws an error, when the
   * second (keep-going) build runs, there is not a race that keeps it as a reverse dep of its
   * children.
   */
  @Test
  public void raceClearingIncompleteValues() throws Exception {
    // Make sure top is enqueued before mid, to avoid a deadlock.
    SkyKey topKey = skyKey("aatop");
    SkyKey midKey = skyKey("zzmid");
    SkyKey badKey = skyKey("bad");
    AtomicBoolean waitForSecondCall = new AtomicBoolean(false);
    CountDownLatch otherThreadWinning = new CountDownLatch(1);
    AtomicReference<Thread> firstThread = new AtomicReference<>();
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (!waitForSecondCall.get()) {
            return;
          }
          if (key.equals(midKey)) {
            if (type == EventType.CREATE_IF_ABSENT) {
              // The first thread to create midKey will not be the first thread to add a reverse dep
              // to it.
              firstThread.compareAndSet(null, Thread.currentThread());
              return;
            }
            if (type == EventType.ADD_REVERSE_DEP) {
              if (order == Order.BEFORE && Thread.currentThread().equals(firstThread.get())) {
                // If this thread created midKey, block until the other thread adds a dep on it.
                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                    otherThreadWinning, "other thread didn't pass this one");
              } else if (order == Order.AFTER
                  && !Thread.currentThread().equals(firstThread.get())) {
                // This thread has added a dep. Allow the other thread to proceed.
                otherThreadWinning.countDown();
              }
            }
          }
        },
        /* deterministic= */ true);
    tester.getOrCreate(topKey).addDependency(midKey).setComputedValue(CONCATENATE);
    tester.getOrCreate(midKey).addDependency(badKey).setComputedValue(CONCATENATE);
    tester.getOrCreate(badKey).setHasError(true);
    EvaluationResult<SkyValue> result = tester.eval(/*keepGoing=*/ false, topKey, midKey);
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(midKey);
    waitForSecondCall.set(true);
    result = tester.eval(/*keepGoing=*/ true, topKey, midKey);
    assertThat(firstThread.get()).isNotNull();
    assertThat(otherThreadWinning.getCount()).isEqualTo(0);
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(midKey);
    assertThatEvaluationResult(result).hasErrorEntryForKeyThat(topKey);
  }

  @Test
  public void breakWithErrorDep() throws Exception {
    SkyKey errorKey = skyKey("my_error_value");
    tester.getOrCreate(errorKey).setHasError(true);
    tester.set("after", new StringValue("after"));
    SkyKey parentKey = skyKey("parent");
    tester
        .getOrCreate(parentKey)
        .addErrorDependency(errorKey, new StringValue("recovered"))
        .setComputedValue(CONCATENATE)
        .addDependency("after");
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, parentKey);
    assertThatEvaluationResult(result).hasSingletonErrorThat(parentKey);
    result = tester.eval(/*keepGoing=*/ true, parentKey);
    assertThatEvaluationResult(result).hasNoError();
    assertThatEvaluationResult(result)
        .hasEntryThat(parentKey)
        .isEqualTo(new StringValue("recoveredafter"));
  }

  @Test
  public void raceConditionWithNoKeepGoingErrors_InflightError() throws Exception {
    // Given a graph of two nodes, errorKey and otherErrorKey,
    SkyKey errorKey = skyKey("errorKey");
    SkyKey otherErrorKey = skyKey("otherErrorKey");

    CountDownLatch errorCommitted = new CountDownLatch(1);

    CountDownLatch otherStarted = new CountDownLatch(1);

    CountDownLatch otherDone = new CountDownLatch(1);

    AtomicInteger numOtherInvocations = new AtomicInteger(0);
    AtomicReference<String> bogusInvocationMessage = new AtomicReference<>(null);
    AtomicReference<String> nonNullValueMessage = new AtomicReference<>(null);

    tester
        .getOrCreate(errorKey)
        .setBuilder(
            (skyKey, env) -> {
              // Given that errorKey waits for otherErrorKey to begin evaluation before completing
              // its evaluation,
              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                  otherStarted, "otherErrorKey's SkyFunction didn't start in time.");
              // And given that errorKey throws an error,
              throw new GenericFunctionException(
                  new SomeErrorException("error"), Transience.PERSISTENT);
            });
    tester
        .getOrCreate(otherErrorKey)
        .setBuilder(
            (skyKey, env) -> {
              otherStarted.countDown();
              int invocations = numOtherInvocations.incrementAndGet();
              // And given that otherErrorKey waits for errorKey's error to be committed before
              // trying to get errorKey's value,
              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                  errorCommitted, "errorKey's error didn't get committed to the graph in time");
              try {
                SkyValue value = env.getValueOrThrow(errorKey, SomeErrorException.class);
                if (value != null) {
                  nonNullValueMessage.set("bogus non-null value " + value);
                }
                if (invocations != 1) {
                  bogusInvocationMessage.set("bogus invocation count: " + invocations);
                }
                otherDone.countDown();
                // And given that otherErrorKey throws an error,
                throw new GenericFunctionException(
                    new SomeErrorException("other"), Transience.PERSISTENT);
              } catch (SomeErrorException e) {
                fail();
                return null;
              }
            });
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (key.equals(errorKey) && type == EventType.SET_VALUE && order == Order.AFTER) {
            errorCommitted.countDown();
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                otherDone, "otherErrorKey's SkyFunction didn't finish in time.");
          }
        },
        /*deterministic=*/ false);

    // When the graph is evaluated in noKeepGoing mode,
    EvaluationResult<StringValue> result =
        tester.eval(/*keepGoing=*/ false, errorKey, otherErrorKey);

    // Then the result reports that an error occurred,
    assertThat(result.hasError()).isTrue();

    // And no value is committed for otherErrorKey,
    assertThat(tester.evaluator.getExistingErrorForTesting(otherErrorKey)).isNull();
    assertThat(tester.evaluator.getExistingValue(otherErrorKey)).isNull();

    // And no value was committed for errorKey,
    assertWithMessage(nonNullValueMessage.get()).that(nonNullValueMessage.get()).isNull();

    // And the SkyFunction for otherErrorKey was evaluated exactly once.
    assertThat(numOtherInvocations.get()).isEqualTo(1);
    assertWithMessage(bogusInvocationMessage.get()).that(bogusInvocationMessage.get()).isNull();
  }

  @Test
  public void absentParent() throws Exception {
    SkyKey errorKey = nonHermeticKey("my_error_value");
    tester.set(errorKey, new StringValue("biding time"));
    SkyKey absentParentKey = skyKey("absentParent");
    tester.getOrCreate(absentParentKey).addDependency(errorKey).setComputedValue(CONCATENATE);
    assertThat(tester.evalAndGet(/*keepGoing=*/ false, absentParentKey))
        .isEqualTo(new StringValue("biding time"));
    tester.getOrCreate(errorKey, /*markAsModified=*/ true).setHasError(true);
    SkyKey newParent = skyKey("newParent");
    tester.getOrCreate(newParent).addDependency(errorKey).setComputedValue(CONCATENATE);
    tester.invalidate();
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, newParent);
    assertThatEvaluationResult(result).hasSingletonErrorThat(newParent);
  }

  @Test
  public void notComparableNotPrunedNoEvent() throws Exception {
    checkNotComparableNotPruned(false);
  }

  @Test
  public void notComparableNotPrunedEvent() throws Exception {
    checkNotComparableNotPruned(true);
  }

  private void checkNotComparableNotPruned(boolean hasEvent) throws Exception {
    SkyKey parent = skyKey("parent");
    SkyKey child = nonHermeticKey("child");
    NotComparableStringValue notComparableString = new NotComparableStringValue("not comparable");
    if (hasEvent) {
      tester.getOrCreate(child).setConstantValue(notComparableString).setWarning("shmoop");
    } else {
      tester.getOrCreate(child).setConstantValue(notComparableString);
    }
    AtomicInteger parentEvaluated = new AtomicInteger();
    StringValue val = new StringValue("some val");
    tester
        .getOrCreate(parent)
        .addDependency(child)
        .setComputedValue(
            (deps, env) -> {
              parentEvaluated.incrementAndGet();
              return val;
            });
    assertThat(tester.evalAndGet(/* keepGoing= */ false, parent)).isEqualTo(val);
    assertThat(parentEvaluated.get()).isEqualTo(1);
    if (hasEvent) {
      assertThatEvents(eventCollector).containsExactly("shmoop");
    } else {
      assertThatEvents(eventCollector).isEmpty();
    }
    eventCollector.clear();

    tester.resetPlayedEvents();
    tester.getOrCreate(child, /*markAsModified=*/ true);
    tester.invalidate();
    assertThat(tester.evalAndGet(/* keepGoing= */ false, parent)).isEqualTo(val);
    assertThat(parentEvaluated.get()).isEqualTo(2);
    if (hasEvent) {
      assertThatEvents(eventCollector).containsExactly("shmoop");
    } else {
      assertThatEvents(eventCollector).isEmpty();
    }
  }

  @Test
  public void changePruningWithEvent() throws Exception {
    SkyKey parent = skyKey("parent");
    SkyKey child = nonHermeticKey("child");
    tester.getOrCreate(child).setConstantValue(new StringValue("child")).setWarning("bloop");
    // Restart once because child isn't ready.
    CountDownLatch parentEvaluated = new CountDownLatch(3);
    StringValue parentVal = new StringValue("parent");
    tester
        .getOrCreate(parent)
        .setBuilder(
            new ChainedFunction(
                parentEvaluated, null, null, false, parentVal, ImmutableList.of(child)));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, parent)).isEqualTo(parentVal);
    assertThat(parentEvaluated.getCount()).isEqualTo(1);
    assertThatEvents(eventCollector).containsExactly("bloop");
    eventCollector.clear();
    tester.resetPlayedEvents();
    tester.getOrCreate(child, /*markAsModified=*/ true);
    tester.invalidate();
    assertThat(tester.evalAndGet(/*keepGoing=*/ false, parent)).isEqualTo(parentVal);
    assertThatEvents(eventCollector).containsExactly("bloop");
    assertThat(parentEvaluated.getCount()).isEqualTo(1);
  }

  @Test
  public void changePruningWithIntermittentEvent() throws Exception {
    String parentEvent = "parent_event";
    String waitEvent = "wait_event";
    String childEvent = "child_event";
    SkyKey wait = skyKey("wait_key");
    SkyKey parent = skyKey("parent_key");
    SkyKey child = nonHermeticKey("child_key");
    StringValue parentStringValue = new StringValue("parent_value");
    StringValue waitStringValue = new StringValue("wait_value");
    CountDownLatch parentEvaluated = new CountDownLatch(2);

    reporter =
        new DelegatingEventHandler(reporter) {
          @Override
          public void handle(Event e) {
            super.handle(e);
            // Release the CountDownLatch every time the parent node fires the event
            if (e.getMessage().equals(parentEvent)) {
              parentEvaluated.countDown();
            }
          }
        };

    tester
        .getOrCreate(wait)
        .setBuilder(
            (skyKey, env) -> {
              // Wait for the parent and child actions to complete before computing wait node
              parentEvaluated.await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS);
              assertThatEvents(eventCollector).containsExactly(childEvent, parentEvent);

              env.getListener().handle(Event.progress(waitEvent));
              return waitStringValue;
            });
    tester
        .getOrCreate(child)
        .setConstantValue(new StringValue("child_value"))
        .setWarning(childEvent);
    tester
        .getOrCreate(parent)
        .addDependency(child)
        .setConstantValue(parentStringValue)
        .setErrorEvent(parentEvent);

    assertThat(tester.evalAndGet(/*keepGoing=*/ false, parent)).isEqualTo(parentStringValue);
    assertThatEvents(eventCollector).containsExactly(childEvent, parentEvent);
    assertThat(parentEvaluated.getCount()).isEqualTo(1);

    // Reset the event collector and mark the child as modified without actually changing values
    eventCollector.clear();
    tester.resetPlayedEvents();
    tester.getOrCreate(child, /*markAsModified=*/ true);
    tester.invalidate();

    EvaluationResult<StringValue> result = tester.eval(false, parent, wait);
    assertThat(result.values()).containsExactly(parentStringValue, waitStringValue);

    // These assertions are to check that all events fired at the end of evaluation.
    assertThat(parentEvaluated.getCount()).isEqualTo(0);
    assertThatEvents(eventCollector).containsExactly(childEvent, parentEvent, waitEvent);
  }

  @Test
  public void depEventPredicate() throws Exception {
    SkyKey parent = skyKey("parent");
    SkyKey excludedDep = skyKey("excludedDep");
    SkyKey includedDep = skyKey("includedDep");
    tester.setEventFilter(
        new EventFilter() {
          @Override
          public boolean storeEvents() {
            return true;
          }

          @Override
          public boolean shouldPropagate(SkyKey depKey, SkyKey primaryKey) {
            return !primaryKey.equals(parent) || depKey.equals(includedDep);
          }
        });
    tester.initialize();
    tester
        .getOrCreate(parent)
        .addDependency(excludedDep)
        .addDependency(includedDep)
        .setComputedValue(CONCATENATE);
    tester
        .getOrCreate(excludedDep)
        .setErrorEvent("excludedDep error message")
        .setConstantValue(new StringValue("excludedDep"));
    tester
        .getOrCreate(includedDep)
        .setErrorEvent("includedDep error message")
        .setConstantValue(new StringValue("includedDep"));
    tester.eval(/* keepGoing= */ false, includedDep, excludedDep);
    assertThatEvents(eventCollector)
        .containsExactly("excludedDep error message", "includedDep error message");
    eventCollector.clear();
    emittedEventState.clear();
    tester.eval(/* keepGoing= */ true, parent);
    assertThatEvents(eventCollector).containsExactly("includedDep error message");
    assertThat(
            ValueWithMetadata.getEvents(
                    tester
                        .evaluator
                        .getExistingEntryAtCurrentlyEvaluatingVersion(parent)
                        .getValueMaybeWithMetadata())
                .toList())
        .containsExactly(Event.error("includedDep error message"));
  }

  // Tests that we have a sane implementation of error transience.
  @Test
  public void errorTransienceBug() throws Exception {
    tester.getOrCreate("key").setHasTransientError(true);
    assertThat(tester.evalAndGetError(/*keepGoing=*/ true, "key").getException()).isNotNull();
    StringValue value = new StringValue("hi");
    tester.getOrCreate("key").setHasTransientError(false).setConstantValue(value);
    tester.invalidateTransientErrors();
    assertThat(tester.evalAndGet("key")).isEqualTo(value);
    // This works because the version of the ValueEntry for the ErrorTransience value is always
    // increased on each InMemoryMemoizingEvaluator#evaluate call. But that's not the only way to
    // implement error transience; another valid implementation would be to unconditionally mark
    // values depending on the ErrorTransience value as being changed (rather than merely dirtied)
    // during invalidation.
  }

  @Test
  public void transientErrorTurningGoodHasNoError() throws Exception {
    initializeTester();
    SkyKey errorKey = skyKey("my_error_value");
    tester.getOrCreate(errorKey).setHasTransientError(true);
    ErrorInfo errorInfo = tester.evalAndGetError(/*keepGoing=*/ true, errorKey);
    assertThat(errorInfo).isNotNull();
    // Re-evaluates to same thing when errors are invalidated
    tester.invalidateTransientErrors();
    errorInfo = tester.evalAndGetError(/*keepGoing=*/ true, errorKey);
    assertThat(errorInfo).isNotNull();
    StringValue value = new StringValue("reformed");
    tester
        .getOrCreate(errorKey, /*markAsModified=*/ false)
        .setHasTransientError(false)
        .setConstantValue(value);
    tester.invalidateTransientErrors();
    StringValue stringValue = (StringValue) tester.evalAndGet(/*keepGoing=*/ true, errorKey);
    assertThat(value).isSameInstanceAs(stringValue);
    // Value builder will now throw, but we should never get to it because it isn't dirty.
    tester.getOrCreate(errorKey, /*markAsModified=*/ false).setHasTransientError(true);
    tester.invalidateTransientErrors();
    stringValue = (StringValue) tester.evalAndGet(/*keepGoing=*/ true, errorKey);
    assertThat(stringValue).isEqualTo(value);
  }

  @Test
  public void transientErrorTurnsGoodOnSecondTry() throws Exception {
    SkyKey leafKey = skyKey("leaf");
    SkyKey errorKey = skyKey("error");
    SkyKey topKey = skyKey("top");
    StringValue value = new StringValue("val");
    tester.getOrCreate(topKey).addDependency(errorKey).setConstantValue(value);
    tester
        .getOrCreate(errorKey)
        .addDependency(leafKey)
        .setConstantValue(value)
        .setHasTransientError(true);
    tester.getOrCreate(leafKey).setConstantValue(new StringValue("leaf"));
    ErrorInfo errorInfo = tester.evalAndGetError(/* keepGoing= */ true, topKey);
    assertThat(errorInfo).isNotNull();
    assertThatErrorInfo(errorInfo).isTransient();
    tester.invalidateTransientErrors();
    errorInfo = tester.evalAndGetError(/*keepGoing=*/ true, topKey);
    assertThat(errorInfo).isNotNull();
    assertThatErrorInfo(errorInfo).isTransient();
    tester.invalidateTransientErrors();
    tester.getOrCreate(errorKey, /*markAsModified=*/ false).setHasTransientError(false);
    assertThat(tester.evalAndGet(/*keepGoing=*/ true, topKey)).isEqualTo(value);
  }

  @Test
  public void deleteInvalidatedValue() throws Exception {
    SkyKey top = skyKey("top");
    SkyKey toDelete = nonHermeticKey("toDelete");
    // Must be a concatenation -- COPY doesn't actually copy.
    tester.getOrCreate(top).addDependency(toDelete).setComputedValue(CONCATENATE);
    tester.set(toDelete, new StringValue("toDelete"));
    SkyValue value = tester.evalAndGet("top");
    SkyKey forceInvalidation = skyKey("forceInvalidation");
    tester.set(forceInvalidation, new StringValue("forceInvalidation"));
    tester.getOrCreate(toDelete, /* markAsModified= */ true);
    tester.invalidate();
    tester.eval(/* keepGoing= */ false, forceInvalidation);
    tester.delete("toDelete");
    WeakReference<SkyValue> ref = new WeakReference<>(value);
    value = null;
    tester.eval(/*keepGoing=*/ false, forceInvalidation);
    tester.invalidate(); // So that invalidation receiver doesn't hang on to reference.
    GcFinalization.awaitClear(ref);
  }

  /**
   * General stress/fuzz test of the evaluator with failure. Construct a large graph, and then throw
   * exceptions during building at various points.
   */
  @Test
  public void twoRailLeftRightDependenciesWithFailure() throws Exception {
    initializeTester();
    SkyKey[] leftValues = new SkyKey[TEST_NODE_COUNT];
    SkyKey[] rightValues = new SkyKey[TEST_NODE_COUNT];
    for (int i = 0; i < TEST_NODE_COUNT; i++) {
      leftValues[i] = nonHermeticKey("left-" + i);
      rightValues[i] = skyKey("right-" + i);
      if (i == 0) {
        tester.getOrCreate(leftValues[i]).addDependency("leaf").setComputedValue(COPY);
        tester.getOrCreate(rightValues[i]).addDependency("leaf").setComputedValue(COPY);
      } else {
        tester
            .getOrCreate(leftValues[i])
            .addDependency(leftValues[i - 1])
            .addDependency(rightValues[i - 1])
            .setComputedValue(new PassThroughSelected(leftValues[i - 1]));
        tester
            .getOrCreate(rightValues[i])
            .addDependency(leftValues[i - 1])
            .addDependency(rightValues[i - 1])
            .setComputedValue(new PassThroughSelected(rightValues[i - 1]));
      }
    }
    tester.set("leaf", new StringValue("leaf"));

    SkyKey lastLeft = nonHermeticKey("left-" + (TEST_NODE_COUNT - 1));
    SkyKey lastRight = skyKey("right-" + (TEST_NODE_COUNT - 1));

    for (int i = 0; i < TESTED_NODES; i++) {
      try {
        tester.getOrCreate(leftValues[i], /* markAsModified= */ true).setHasError(true);
        tester.invalidate();
        EvaluationResult<StringValue> result =
            tester.eval(/* keepGoing= */ false, lastLeft, lastRight);
        assertThat(result.hasError()).isTrue();
        tester.differencer.invalidate(ImmutableList.of(leftValues[i]));
        tester.invalidate();
        result = tester.eval(/* keepGoing= */ false, lastLeft, lastRight);
        assertThat(result.hasError()).isTrue();
        tester.getOrCreate(leftValues[i], /*markAsModified=*/ true).setHasError(false);
        tester.invalidate();
        result = tester.eval(/* keepGoing= */ false, lastLeft, lastRight);
        assertThat(result.get(lastLeft)).isEqualTo(new StringValue("leaf"));
        assertThat(result.get(lastRight)).isEqualTo(new StringValue("leaf"));
      } catch (Exception e) {
        System.err.println("twoRailLeftRightDependenciesWithFailure exception on run " + i);
        throw e;
      }
    }
  }

  @Test
  public void valueInjection() throws Exception {
    SkyKey key = nonHermeticKey("new_value");
    Delta delta = Delta.justNew(new StringValue("val"));

    tester.differencer.inject(ImmutableMap.of(key, delta));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionOverExistingEntry() throws Exception {
    SkyKey key = nonHermeticKey("key");
    Delta delta = Delta.justNew(new StringValue("val"));

    tester.getOrCreate(key).setConstantValue(new StringValue("old_val"));
    tester.differencer.inject(ImmutableMap.of(key, delta));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionOverExistingDirtyEntry() throws Exception {
    SkyKey key = nonHermeticKey("key");
    Delta delta = Delta.justNew(new StringValue("val"));

    tester.getOrCreate(key).setConstantValue(new StringValue("old_val"));
    tester.differencer.inject(ImmutableMap.of(key, delta));
    tester.eval(/*keepGoing=*/ false, new SkyKey[0]); // Create the value.

    tester.differencer.invalidate(ImmutableList.of(key));
    tester.eval(/*keepGoing=*/ false, new SkyKey[0]); // Mark value as dirty.

    tester.differencer.inject(ImmutableMap.of(key, delta));
    tester.eval(/*keepGoing=*/ false, new SkyKey[0]); // Inject again.
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionOverExistingEntryMarkedForInvalidation() throws Exception {
    SkyKey key = nonHermeticKey("key");
    Delta delta = Delta.justNew(new StringValue("val"));

    tester.getOrCreate(key).setConstantValue(new StringValue("old_val"));
    tester.differencer.invalidate(ImmutableList.of(key));
    tester.differencer.inject(ImmutableMap.of(key, delta));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionOverExistingEntryMarkedForDeletion() throws Exception {
    SkyKey key = nonHermeticKey("key");
    Delta delta = Delta.justNew(new StringValue("val"));

    tester.getOrCreate(key).setConstantValue(new StringValue("old_val"));
    tester.evaluator.delete(Predicates.alwaysTrue());
    tester.differencer.inject(ImmutableMap.of(key, delta));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionOverExistingEqualEntryMarkedForInvalidation() throws Exception {
    SkyKey key = nonHermeticKey("key");
    Delta delta = Delta.justNew(new StringValue("val"));

    tester.differencer.inject(ImmutableMap.of(key, delta));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());

    tester.differencer.invalidate(ImmutableList.of(key));
    tester.differencer.inject(ImmutableMap.of(key, delta));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionOverExistingEqualEntryMarkedForDeletion() throws Exception {
    SkyKey key = nonHermeticKey("key");
    Delta delta = Delta.justNew(new StringValue("val"));

    tester.differencer.inject(ImmutableMap.of(key, delta));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());

    tester.evaluator.delete(Predicates.alwaysTrue());
    tester.differencer.inject(ImmutableMap.of(key, delta));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionOverValueWithDeps() throws Exception {
    SkyKey key = nonHermeticKey("key");
    SkyKey otherKey = nonHermeticKey("other");
    Delta delta = Delta.justNew(new StringValue("val"));
    StringValue prevVal = new StringValue("foo");

    tester.getOrCreate(otherKey).setConstantValue(prevVal);
    tester.getOrCreate(key).addDependency(otherKey).setComputedValue(COPY);
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(prevVal);
    tester.differencer.inject(ImmutableMap.of(key, delta));
    StringValue depVal = new StringValue("newfoo");
    tester.getOrCreate(otherKey).setConstantValue(depVal);
    tester.differencer.invalidate(ImmutableList.of(otherKey));
    // Injected value is ignored for value with deps.
    assertThat(tester.evalAndGet(/*keepGoing=*/ false, key)).isEqualTo(depVal);
  }

  @Test
  public void valueInjectionOverEqualValueWithDeps() throws Exception {
    SkyKey key = nonHermeticKey("key");
    Delta delta = Delta.justNew(new StringValue("val"));

    tester.getOrCreate("other").setConstantValue(delta.newValue());
    tester.getOrCreate(key).addDependency("other").setComputedValue(COPY);
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());
    tester.differencer.inject(ImmutableMap.of(key, delta));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, key)).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionOverValueWithErrors() throws Exception {
    SkyKey key = nonHermeticKey("key");
    Delta delta = Delta.justNew(new StringValue("val"));

    tester.getOrCreate(key).setHasError(true);
    tester.evalAndGetError(/*keepGoing=*/ true, key);

    tester.differencer.inject(ImmutableMap.of(key, delta));
    assertThat(tester.evalAndGet(false, key)).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionInvalidatesReverseDeps() throws Exception {
    SkyKey childKey = nonHermeticKey("child");
    SkyKey parentKey = skyKey("parent");
    StringValue oldVal = new StringValue("old_val");

    tester.getOrCreate(childKey).setConstantValue(oldVal);
    tester.getOrCreate(parentKey).addDependency(childKey).setComputedValue(COPY);

    EvaluationResult<SkyValue> result = tester.eval(false, parentKey);
    assertThat(result.hasError()).isFalse();
    assertThat(result.get(parentKey)).isEqualTo(oldVal);

    Delta delta = Delta.justNew(new StringValue("val"));
    tester.differencer.inject(ImmutableMap.of(childKey, delta));
    assertThat(tester.evalAndGet(/* keepGoing= */ false, childKey)).isEqualTo(delta.newValue());
    // Injecting a new child should have invalidated the parent.
    assertThat(tester.getExistingValue("parent")).isNull();

    tester.eval(false, childKey);
    assertThat(tester.getExistingValue(childKey)).isEqualTo(delta.newValue());
    assertThat(tester.getExistingValue("parent")).isNull();
    assertThat(tester.evalAndGet("parent")).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionOverExistingEqualEntryDoesNotInvalidate() throws Exception {
    SkyKey childKey = nonHermeticKey("child");
    SkyKey parentKey = skyKey("parent");
    Delta delta = Delta.justNew(new StringValue("same_val"));

    tester.getOrCreate(parentKey).addDependency(childKey).setComputedValue(COPY);
    tester.getOrCreate(childKey).setConstantValue(new StringValue("same_val"));
    assertThat(tester.evalAndGet("parent")).isEqualTo(delta.newValue());

    tester.differencer.inject(ImmutableMap.of(childKey, delta));
    assertThat(tester.getExistingValue(childKey)).isEqualTo(delta.newValue());
    // Since we are injecting an equal value, the parent should not have been invalidated.
    assertThat(tester.getExistingValue("parent")).isEqualTo(delta.newValue());
  }

  @Test
  public void valueInjectionInterrupt() throws Exception {
    SkyKey key = nonHermeticKey("key");
    Delta delta = Delta.justNew(new StringValue("val"));

    tester.differencer.inject(ImmutableMap.of(key, delta));
    Thread.currentThread().interrupt();
    assertThrows(InterruptedException.class, () -> tester.evalAndGet(/*keepGoing=*/ false, key));
    SkyValue newVal = tester.evalAndGet(/*keepGoing=*/ false, key);
    assertThat(newVal).isEqualTo(delta.newValue());
  }

  protected void runTestPersistentErrorsNotRerun(boolean includeTransientError) throws Exception {
    SkyKey topKey = skyKey("top");
    SkyKey transientErrorKey = skyKey("transientError");
    SkyKey persistentErrorKey1 = skyKey("persistentError1");
    SkyKey persistentErrorKey2 = skyKey("persistentError2");

    TestFunction topFunction =
        tester
            .getOrCreate(topKey)
            .addErrorDependency(persistentErrorKey1, new StringValue("doesn't matter"))
            .setHasError(true);
    tester.getOrCreate(persistentErrorKey1).setHasError(true);
    if (includeTransientError) {
      topFunction.addErrorDependency(transientErrorKey, new StringValue("doesn't matter"));
      tester
          .getOrCreate(transientErrorKey)
          .addErrorDependency(persistentErrorKey2, new StringValue("doesn't matter"))
          .setHasTransientError(true);
    }
    tester.getOrCreate(persistentErrorKey2).setHasError(true);

    tester.evalAndGetError(/*keepGoing=*/ true, topKey);
    if (includeTransientError) {
      assertThat(tester.getEnqueuedValues())
          .containsExactly(topKey, transientErrorKey, persistentErrorKey1, persistentErrorKey2);
    } else {
      assertThat(tester.getEnqueuedValues()).containsExactly(topKey, persistentErrorKey1);
    }

    tester.invalidate();
    tester.invalidateTransientErrors();
    tester.evalAndGetError(/*keepGoing=*/ true, topKey);
    if (includeTransientError) {
      // TODO(bazel-team): We can do better here once we implement change pruning for errors.
      assertThat(tester.getEnqueuedValues()).containsExactly(topKey, transientErrorKey);
    } else {
      assertThat(tester.getEnqueuedValues()).isEmpty();
    }
  }

  @Test
  public void persistentErrorsNotRerun() throws Exception {
    runTestPersistentErrorsNotRerun(/*includeTransientError=*/ true);
  }

  /**
   * The following two tests check that the evaluator shuts down properly when encountering an error
   * that is marked dirty but later verified to be unchanged from a prior build. In that case, the
   * invariant that its parents are not enqueued for evaluation should be maintained.
   */
  /**
   * Test that a parent of a cached but invalidated error doesn't successfully build. First build
   * the error. Then invalidate the error via a dependency (so it will not actually change) and
   * build two new parents. Parent A will request error and abort since error isn't done yet. error
   * is then revalidated, and A is restarted. If A does not throw upon encountering the error, and
   * instead sets its value, then we throw in parent B, which waits for error to be done before
   * requesting it. Then there will be the impossible situation of a node that was built during this
   * evaluation depending on a node in error.
   */
  @Test
  public void shutDownBuildOnCachedError_Done() throws Exception {
    // errorKey will be invalidated due to its dependence on invalidatedKey, but later revalidated
    // since invalidatedKey re-evaluates to the same value on a subsequent build.
    SkyKey errorKey = skyKey("error");
    SkyKey invalidatedKey = nonHermeticKey("invalidated-leaf");
    tester.set(invalidatedKey, new StringValue("invalidated-leaf-value"));
    tester.getOrCreate(errorKey).addDependency(invalidatedKey).setHasError(true);
    // Names are alphabetized in reverse deps of errorKey.
    SkyKey fastToRequestSlowToSetValueKey = skyKey("A-slow-set-value-parent");
    SkyKey failingKey = skyKey("B-fast-fail-parent");
    tester
        .getOrCreate(fastToRequestSlowToSetValueKey)
        .addDependency(errorKey)
        .setComputedValue(CONCATENATE);
    tester.getOrCreate(failingKey).addDependency(errorKey).setComputedValue(CONCATENATE);
    // We only want to force a particular order of operations at some points during evaluation.
    AtomicBoolean synchronizeThreads = new AtomicBoolean(false);
    // We don't expect slow-set-value to actually be built, but if it is, we wait for it.
    CountDownLatch slowBuilt = new CountDownLatch(1);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (!synchronizeThreads.get()) {
            return;
          }
          if (type == EventType.GET_LIFECYCLE_STATE && key.equals(failingKey)) {
            // Wait for the build to abort or for the other node to incorrectly build.
            try {
              assertThat(slowBuilt.await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS))
                  .isTrue();
            } catch (InterruptedException e) {
              // This is ok, because it indicates the build is shutting down.
              Thread.currentThread().interrupt();
            }
          } else if (type == EventType.SET_VALUE
              && key.equals(fastToRequestSlowToSetValueKey)
              && order == Order.AFTER) {
            // This indicates a problem -- this parent shouldn't be built since it depends on
            // an error.
            slowBuilt.countDown();
            // Before this node actually sets its value (and then throws an exception) we wait
            // for the other node to throw an exception.
            try {
              Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
              throw new IllegalStateException("uninterrupted in " + key);
            } catch (InterruptedException e) {
              Thread.currentThread().interrupt();
            }
          }
        },
        /* deterministic= */ true);
    // Initialize graph.
    tester.eval(/*keepGoing=*/ true, errorKey);
    tester.getOrCreate(invalidatedKey, /*markAsModified=*/ true);
    tester.invalidate();
    synchronizeThreads.set(true);
    tester.eval(/*keepGoing=*/ false, fastToRequestSlowToSetValueKey, failingKey);
  }

  /**
   * Test that the invalidated parent of a cached but invalidated error doesn't get marked clean.
   * First build the parent -- it will contain an error. Then invalidate the error via a dependency
   * (so it will not actually change) and then build the parent and another node that depends on the
   * error. The other node will wait to throw until the parent is signaled that all of its
   * dependencies are done, or until it is interrupted. If it throws, the parent will be
   * VERIFIED_CLEAN but not done, which is not a valid state once evaluation shuts down. The
   * evaluator avoids this situation by throwing when the error is encountered, even though the
   * error isn't evaluated or requested by an evaluating node.
   */
  @Test
  public void shutDownBuildOnCachedError_Verified() throws Exception {
    // TrackingProgressReceiver does unnecessary examination of node values.
    initializeTester(createTrackingProgressReceiver(/* checkEvaluationResults= */ false));
    // errorKey will be invalidated due to its dependence on invalidatedKey, but later revalidated
    // since invalidatedKey re-evaluates to the same value on a subsequent build.
    SkyKey errorKey = skyKey("error");
    SkyKey invalidatedKey = nonHermeticKey("invalidated-leaf");
    SkyKey changedKey = nonHermeticKey("changed-leaf");
    tester.set(invalidatedKey, new StringValue("invalidated-leaf-value"));
    tester.set(changedKey, new StringValue("changed-leaf-value"));
    // Names are alphabetized in reverse deps of errorKey.
    SkyKey cachedParentKey = skyKey("A-cached-parent");
    SkyKey uncachedParentKey = skyKey("B-uncached-parent");
    tester.getOrCreate(errorKey).addDependency(invalidatedKey).setHasError(true);
    tester.getOrCreate(cachedParentKey).addDependency(errorKey).setComputedValue(CONCATENATE);
    tester
        .getOrCreate(uncachedParentKey)
        .addDependency(changedKey)
        .addDependency(errorKey)
        .setComputedValue(CONCATENATE);
    // We only want to force a particular order of operations at some points during evaluation. In
    // particular, we don't want to force anything during error bubbling.
    AtomicBoolean synchronizeThreads = new AtomicBoolean(false);
    CountDownLatch shutdownAwaiterStarted = new CountDownLatch(1);
    injectGraphListenerForTesting(
        new Listener() {
          private final CountDownLatch cachedSignaled = new CountDownLatch(1);

          @Override
          public void accept(SkyKey key, EventType type, Order order, Object context) {
            if (!synchronizeThreads.get() || order != Order.BEFORE || type != EventType.SIGNAL) {
              return;
            }
            TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                shutdownAwaiterStarted, "shutdown awaiter not started");
            if (key.equals(uncachedParentKey)) {
              // When the uncached parent is first signaled by its changed dep, make sure that
              // we wait until the cached parent is signaled too.
              try {
                assertThat(cachedSignaled.await(TestUtils.WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS))
                    .isTrue();
              } catch (InterruptedException e) {
                // Before the relevant bug was fixed, this code was not interrupted, and the
                // uncached parent got to build, yielding an inconsistent state at a later point
                // during evaluation. With the bugfix, the cached parent is never signaled
                // before the evaluator shuts down, and so the above code is interrupted.
                Thread.currentThread().interrupt();
              }
            } else if (key.equals(cachedParentKey)) {
              // This branch should never be reached by a well-behaved evaluator, since when the
              // error node is reached, the evaluator should shut down. However, we don't test
              // for that behavior here because that would be brittle and we expect that such an
              // evaluator will crash hard later on in any case.
              cachedSignaled.countDown();
              try {
                // Sleep until we're interrupted by the evaluator, so we know it's shutting
                // down.
                Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
                Thread currentThread = Thread.currentThread();
                throw new IllegalStateException(
                    "no interruption in time in "
                        + key
                        + " for "
                        + (currentThread.isInterrupted() ? "" : "un")
                        + "interrupted "
                        + currentThread
                        + " with hash "
                        + System.identityHashCode(currentThread)
                        + " at "
                        + System.currentTimeMillis());
              } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
              }
            }
          }
        },
        /* deterministic= */ true);
    // Initialize graph.
    tester.eval(/*keepGoing=*/ true, cachedParentKey, uncachedParentKey);
    tester.getOrCreate(invalidatedKey, /*markAsModified=*/ true);
    tester.set(changedKey, new StringValue("new value"));
    tester.invalidate();
    synchronizeThreads.set(true);
    SkyKey waitForShutdownKey = skyKey("wait-for-shutdown");
    tester
        .getOrCreate(waitForShutdownKey)
        .setBuilder(
            (skyKey, env) -> {
              shutdownAwaiterStarted.countDown();
              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                  ((SkyFunctionEnvironment) env).getExceptionLatchForTesting(),
                  "exception not thrown");
              // Threadpool is shutting down. Don't try to synchronize anything in the future
              // during error bubbling.
              synchronizeThreads.set(false);
              throw new InterruptedException();
            });
    EvaluationResult<StringValue> result =
        tester.eval(/*keepGoing=*/ false, cachedParentKey, uncachedParentKey, waitForShutdownKey);
    assertWithMessage(result.toString()).that(result.hasError()).isTrue();
    tester.getOrCreate(invalidatedKey, /*markAsModified=*/ true);
    tester.invalidate();
    result = tester.eval(/*keepGoing=*/ false, cachedParentKey, uncachedParentKey);
    assertWithMessage(result.toString()).that(result.hasError()).isTrue();
  }

  /**
   * Tests that a race between a node being marked clean and another node requesting it is benign.
   * Here, we first evaluate errorKey, depending on invalidatedKey. Then we invalidate
   * invalidatedKey (without actually changing it) and evaluate errorKey and topKey together.
   * Through forced synchronization, we make sure that the following sequence of events happens:
   *
   * <ol>
   *   <li>topKey requests errorKey;
   *   <li>errorKey is marked clean;
   *   <li>topKey finishes its first evaluation and registers its deps;
   *   <li>topKey restarts, since it sees that its only dep, errorKey, is done;
   *   <li>topKey sees the error thrown by errorKey and throws the error, shutting down the
   *       threadpool;
   * </ol>
   */
  @Test
  public void cachedErrorCausesRestart() throws Exception {
    // TrackingProgressReceiver does unnecessary examination of node values.
    initializeTester(createTrackingProgressReceiver(/* checkEvaluationResults= */ false));
    SkyKey errorKey = skyKey("error");
    SkyKey invalidatedKey = nonHermeticKey("invalidated");
    SkyKey topKey = skyKey("top");
    tester.getOrCreate(errorKey).addDependency(invalidatedKey).setHasError(true);
    tester.getOrCreate(invalidatedKey).setConstantValue(new StringValue("constant"));
    CountDownLatch topSecondEval = new CountDownLatch(2);
    CountDownLatch topRequestedError = new CountDownLatch(1);
    CountDownLatch errorMarkedClean = new CountDownLatch(1);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (errorKey.equals(key) && type == EventType.MARK_CLEAN) {
            if (order == Order.BEFORE) {
              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                  topRequestedError, "top didn't request");
            } else {
              errorMarkedClean.countDown();
              TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                  topSecondEval, "top didn't restart");
              // Make sure that the other thread notices the error and interrupts this thread.
              try {
                Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
              } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
              }
            }
          }
        },
        /* deterministic= */ false);
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, errorKey);
    assertThatEvaluationResult(result).hasError();
    assertThatEvaluationResult(result)
        .hasErrorEntryForKeyThat(errorKey)
        .hasExceptionThat()
        .isNotNull();
    tester
        .getOrCreate(topKey)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) throws InterruptedException {
                topSecondEval.countDown();
                env.getValue(errorKey);
                topRequestedError.countDown();
                assertThat(env.valuesMissing()).isTrue();
                TrackingAwaiter.INSTANCE.awaitLatchAndTrackExceptions(
                    errorMarkedClean, "error not marked clean");
                return null;
              }
            });
    tester.getOrCreate(invalidatedKey, /*markAsModified=*/ true);
    tester.invalidate();
    EvaluationResult<StringValue> result2 = tester.eval(/*keepGoing=*/ false, errorKey, topKey);
    assertThatEvaluationResult(result2).hasError();
    assertThatEvaluationResult(result2)
        .hasErrorEntryForKeyThat(errorKey)
        .hasExceptionThat()
        .isNotNull();
    assertThatEvaluationResult(result2)
        .hasErrorEntryForKeyThat(topKey)
        .hasExceptionThat()
        .isNotNull();
  }

  @Test
  public void cachedChildErrorDepWithSiblingDepOnNoKeepGoingEval() throws Exception {
    SkyKey parent1Key = skyKey("parent1");
    SkyKey parent2Key = skyKey("parent2");
    SkyKey errorKey = nonHermeticKey("error");
    SkyKey otherKey = skyKey("other");
    SkyFunction parentBuilder =
        (skyKey, env) -> {
          env.getValue(errorKey);
          env.getValue(otherKey);
          if (env.valuesMissing()) {
            return null;
          }
          return new StringValue("parent");
        };
    tester.getOrCreate(parent1Key).setBuilder(parentBuilder);
    tester.getOrCreate(parent2Key).setBuilder(parentBuilder);
    tester.getOrCreate(errorKey).setConstantValue(new StringValue("no error yet"));
    tester.getOrCreate(otherKey).setConstantValue(new StringValue("other"));
    tester.eval(/*keepGoing=*/ true, parent1Key);
    tester.eval(/*keepGoing=*/ false, parent2Key);
    tester.getOrCreate(errorKey, /*markAsModified=*/ true).setHasError(true);
    tester.invalidate();
    tester.eval(/*keepGoing=*/ true, parent1Key);
    tester.eval(/*keepGoing=*/ false, parent2Key);
  }

  private void injectGraphListenerForTesting(Listener listener, boolean deterministic) {
    tester.evaluator.injectGraphTransformerForTesting(
        DeterministicHelper.makeTransformer(listener, deterministic));
  }

  private void makeGraphDeterministic() {
    tester.evaluator.injectGraphTransformerForTesting(DeterministicHelper.MAKE_DETERMINISTIC);
  }

  private static final class PassThroughSelected implements ValueComputer {
    private final SkyKey key;

    PassThroughSelected(SkyKey key) {
      this.key = key;
    }

    @Override
    public SkyValue compute(Map<SkyKey, SkyValue> deps, SkyFunction.Environment env) {
      return Preconditions.checkNotNull(deps.get(key));
    }
  }

  private void removedNodeComesBack() throws Exception {
    SkyKey top = nonHermeticKey("top");
    SkyKey mid = skyKey("mid");
    SkyKey leaf = nonHermeticKey("leaf");
    // When top depends on mid, which depends on leaf,
    tester.getOrCreate(top).addDependency(mid).setComputedValue(CONCATENATE);
    tester.getOrCreate(mid).addDependency(leaf).setComputedValue(CONCATENATE);
    StringValue leafValue = new StringValue("leaf");
    tester.set(leaf, leafValue);
    // Then when top is evaluated, its value is as expected.
    assertThat(tester.evalAndGet(/* keepGoing= */ true, top)).isEqualTo(leafValue);
    // When top is changed to no longer depend on mid,
    StringValue topValue = new StringValue("top");
    tester
        .getOrCreate(top, /* markAsModified= */ true)
        .removeDependency(mid)
        .setComputedValue(null)
        .setConstantValue(topValue);
    // And leaf is invalidated,
    tester.getOrCreate(leaf, /*markAsModified=*/ true);
    // Then when top is evaluated, its value is as expected,
    tester.invalidate();
    assertThat(tester.evalAndGet(/*keepGoing=*/ true, top)).isEqualTo(topValue);
      // And there is no value for mid in the graph,
      assertThat(tester.evaluator.getExistingValue(mid)).isNull();
      assertThat(tester.evaluator.getExistingErrorForTesting(mid)).isNull();
      // Or for leaf.
      assertThat(tester.evaluator.getExistingValue(leaf)).isNull();
      assertThat(tester.evaluator.getExistingErrorForTesting(leaf)).isNull();

    // When top is changed to depend directly on leaf,
    tester
        .getOrCreate(top, /*markAsModified=*/ true)
        .addDependency(leaf)
        .setConstantValue(null)
        .setComputedValue(CONCATENATE);
    // Then when top is evaluated, its value is as expected,
    tester.invalidate();
    assertThat(tester.evalAndGet(/*keepGoing=*/ true, top)).isEqualTo(leafValue);
      // and there is no value for mid in the graph,
      assertThat(tester.evaluator.getExistingValue(mid)).isNull();
      assertThat(tester.evaluator.getExistingErrorForTesting(mid)).isNull();
  }

  // Tests that a removed and then reinstated node doesn't try to invalidate its erstwhile parent
  // when it is invalidated.
  @Test
  public void removedNodeComesBackAndInvalidates() throws Exception {
    removedNodeComesBack();
    // When leaf is invalidated again,
    tester.getOrCreate(skyKey("leaf"), /* markAsModified= */ true);
    // Then when top is evaluated, its value is as expected.
    tester.invalidate();
    assertThat(tester.evalAndGet(/* keepGoing= */ true, nonHermeticKey("top")))
        .isEqualTo(new StringValue("leaf"));
  }

  // Tests that a removed and then reinstated node behaves properly when its parent disappears and
  // then reappears.
  @Test
  public void removedNodeComesBackAndOtherInvalidates() throws Exception {
    removedNodeComesBack();
    SkyKey top = nonHermeticKey("top");
    SkyKey mid = skyKey("mid");
    SkyKey leaf = nonHermeticKey("leaf");
    // When top is invalidated again,
    tester.getOrCreate(top, /* markAsModified= */ true).removeDependency(leaf).addDependency(mid);
    // Then when top is evaluated, its value is as expected.
    tester.invalidate();
    assertThat(tester.evalAndGet(/* keepGoing= */ true, top)).isEqualTo(new StringValue("leaf"));
  }

  // Tests that a removed and then reinstated node doesn't have a reverse dep on a former parent.
  @Test
  public void removedInvalidatedNodeComesBackAndOtherInvalidates() throws Exception {
    SkyKey top = nonHermeticKey("top");
    SkyKey leaf = nonHermeticKey("leaf");
    // When top depends on leaf,
    tester.getOrCreate(top).addDependency(leaf).setComputedValue(CONCATENATE);
    StringValue leafValue = new StringValue("leaf");
    tester.set(leaf, leafValue);
    // Then when top is evaluated, its value is as expected.
    assertThat(tester.evalAndGet(/* keepGoing= */ true, top)).isEqualTo(leafValue);
    // When top is changed to no longer depend on leaf,
    StringValue topValue = new StringValue("top");
    tester
        .getOrCreate(top, /* markAsModified= */ true)
        .removeDependency(leaf)
        .setComputedValue(null)
        .setConstantValue(topValue);
    // And leaf is invalidated,
    tester.getOrCreate(leaf, /*markAsModified=*/ true);
    // Then when top is evaluated, its value is as expected,
    tester.invalidate();
    assertThat(tester.evalAndGet(/*keepGoing=*/ true, top)).isEqualTo(topValue);
      // And there is no value for leaf in the graph.
      assertThat(tester.evaluator.getExistingValue(leaf)).isNull();
      assertThat(tester.evaluator.getExistingErrorForTesting(leaf)).isNull();
    // When leaf is evaluated, so that it is present in the graph again,
    assertThat(tester.evalAndGet(/*keepGoing=*/ true, leaf)).isEqualTo(leafValue);
    // And top is changed to depend on leaf again,
    tester
        .getOrCreate(top, /*markAsModified=*/ true)
        .addDependency(leaf)
        .setConstantValue(null)
        .setComputedValue(CONCATENATE);
    // Then when top is evaluated, its value is as expected.
    tester.invalidate();
    assertThat(tester.evalAndGet(/*keepGoing=*/ true, top)).isEqualTo(leafValue);
  }

  @Test
  public void cleanReverseDepFromDirtyNodeNotInBuild() throws Exception {
    SkyKey topKey = nonHermeticKey("top");
    SkyKey inactiveKey = nonHermeticKey("inactive");
    Thread mainThread = Thread.currentThread();
    AtomicBoolean shouldInterrupt = new AtomicBoolean(false);
    injectGraphListenerForTesting(
        (key, type, order, context) -> {
          if (shouldInterrupt.get()
              && key.equals(topKey)
              && type == EventType.IS_READY
              && order == Order.BEFORE) {
            mainThread.interrupt();
            shouldInterrupt.set(false);
            try {
              // Make sure threadpool propagates interrupt.
              Thread.sleep(TestUtils.WAIT_TIMEOUT_MILLISECONDS);
            } catch (InterruptedException e) {
              Thread.currentThread().interrupt();
            }
          }
        },
        /* deterministic= */ false);
    // When top depends on inactive,
    tester.getOrCreate(topKey).addDependency(inactiveKey).setComputedValue(COPY);
    StringValue val = new StringValue("inactive");
    // And inactive is constant,
    tester.set(inactiveKey, val);
    // Then top evaluates normally.
    assertThat(tester.evalAndGet(/*keepGoing=*/ true, topKey)).isEqualTo(val);
    // When evaluation will be interrupted as soon as top starts evaluating,
    shouldInterrupt.set(true);
    // And inactive is dirty,
    tester.getOrCreate(inactiveKey, /*markAsModified=*/ true);
    // And so is top,
    tester.getOrCreate(topKey, /*markAsModified=*/ true);
    tester.invalidate();
    assertThrows(InterruptedException.class, () -> tester.eval(/*keepGoing=*/ false, topKey));
    // But inactive is still present,
    assertThat(tester.evaluator.getExistingEntryAtCurrentlyEvaluatingVersion(inactiveKey))
        .isNotNull();
    // And still dirty,
    assertThat(tester.evaluator.getExistingEntryAtCurrentlyEvaluatingVersion(inactiveKey).isDirty())
        .isTrue();
    // And re-evaluates successfully,
    assertThat(tester.evalAndGet(/*keepGoing=*/ true, inactiveKey)).isEqualTo(val);
    // But top is gone from the graph,
    assertThat(tester.evaluator.getExistingEntryAtCurrentlyEvaluatingVersion(topKey)).isNull();
    // And we can successfully invalidate and re-evaluate inactive again.
    tester.getOrCreate(inactiveKey, /*markAsModified=*/ true);
    tester.invalidate();
    assertThat(tester.evalAndGet(/*keepGoing=*/ true, inactiveKey)).isEqualTo(val);
  }

  @Test
  public void errorChanged() throws Exception {
    SkyKey error = nonHermeticKey("error");
    tester.getOrCreate(error).setHasError(true);
    assertThatErrorInfo(tester.evalAndGetError(/*keepGoing=*/ true, error))
        .hasExceptionThat()
        .isNotNull();
    tester.getOrCreate(error, /*markAsModified=*/ true);
    tester.invalidate();
    assertThatErrorInfo(tester.evalAndGetError(/*keepGoing=*/ true, error))
        .hasExceptionThat()
        .isNotNull();
  }

  @Test
  public void duplicateUnfinishedDeps_NoKeepGoing() throws Exception {
    runTestDuplicateUnfinishedDeps(/*keepGoing=*/ false);
  }

  @Test
  public void duplicateUnfinishedDeps_KeepGoing() throws Exception {
    runTestDuplicateUnfinishedDeps(/*keepGoing=*/ true);
  }

  @Test
  public void externalDep() throws Exception {
    externalDep(1, 0);
    externalDep(2, 0);
    externalDep(1, 1);
    externalDep(1, 2);
    externalDep(2, 1);
    externalDep(2, 2);
  }

  private void externalDep(int firstPassCount, int secondPassCount) throws Exception {
    SkyKey parentKey = skyKey("parentKey");
    CountDownLatch firstPassLatch = new CountDownLatch(1);
    CountDownLatch secondPassLatch = new CountDownLatch(1);
    tester
        .getOrCreate(parentKey)
        .setBuilder(
            new SkyFunction() {
              // Skyframe doesn't have native support for continuations, so we use fields here. A
              // simple continuation API in Skyframe could be Environment providing a
              // setContinuation(SkyContinuation) method, where SkyContinuation provides a compute
              // method similar to SkyFunction. When restarting the node, Skyframe would then call
              // the continuation rather than the original SkyFunction. If we do that, we should
              // consider only allowing calls to dependOnFuture in combination with setContinuation.
              private List<SettableFuture<SkyValue>> firstPass;
              private List<SettableFuture<SkyValue>> secondPass;

              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) {
                if (firstPass == null) {
                  firstPass = new ArrayList<>();
                  for (int i = 0; i < firstPassCount; i++) {
                    SettableFuture<SkyValue> future = SettableFuture.create();
                    firstPass.add(future);
                    env.dependOnFuture(future);
                  }
                  assertThat(env.valuesMissing()).isTrue();
                  Thread helper =
                      new Thread(
                          () -> {
                            try {
                              firstPassLatch.await();
                              for (int i = 0; i < firstPassCount; i++) {
                                firstPass.get(i).set(new StringValue("value1"));
                              }
                            } catch (InterruptedException e) {
                              throw new RuntimeException(e);
                            }
                          });
                  helper.start();
                  return null;
                } else if (secondPass == null && secondPassCount > 0) {
                  for (int i = 0; i < firstPassCount; i++) {
                    assertThat(firstPass.get(i).isDone()).isTrue();
                  }
                  secondPass = new ArrayList<>();
                  for (int i = 0; i < secondPassCount; i++) {
                    SettableFuture<SkyValue> future = SettableFuture.create();
                    secondPass.add(future);
                    env.dependOnFuture(future);
                  }
                  assertThat(env.valuesMissing()).isTrue();
                  Thread helper =
                      new Thread(
                          () -> {
                            try {
                              secondPassLatch.await();
                              for (int i = 0; i < secondPassCount; i++) {
                                secondPass.get(i).set(new StringValue("value2"));
                              }
                            } catch (InterruptedException e) {
                              throw new RuntimeException(e);
                            }
                          });
                  helper.start();
                  return null;
                }
                for (int i = 0; i < secondPassCount; i++) {
                  assertThat(secondPass.get(i).isDone()).isTrue();
                }
                return new StringValue("done!");
              }
            });
    tester.evaluator.injectGraphTransformerForTesting(
        NotifyingHelper.makeNotifyingTransformer(
            new Listener() {
              private boolean firstPassDone;

              @Override
              public void accept(SkyKey key, EventType type, Order order, Object context) {
                // NodeEntry.addExternalDep is called as part of bookkeeping at the end of
                // AbstractParallelEvaluator.Evaluate#run.
                if (key == parentKey && type == EventType.ADD_EXTERNAL_DEP) {
                  if (!firstPassDone) {
                    firstPassLatch.countDown();
                    firstPassDone = true;
                  } else {
                    secondPassLatch.countDown();
                  }
                }
              }
            }));
    EvaluationResult<StringValue> result = tester.eval(/*keepGoing=*/ false, parentKey);
    assertThat(result.hasError()).isFalse();
    assertThat(result.get(parentKey)).isEqualTo(new StringValue("done!"));
  }

  private void runTestDuplicateUnfinishedDeps(boolean keepGoing) throws Exception {
    SkyKey parentKey = skyKey("parent");
    SkyKey childKey = skyKey("child");
    SkyValue childValue = new StringValue("child");
    tester
        .getOrCreate(childKey)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env) {
                if (keepGoing) {
                  return childValue;
                } else {
                  throw new IllegalStateException("shouldn't get here");
                }
              }
            });
    SomeErrorException parentExn = new SomeErrorException("bad");
    AtomicInteger numParentComputeCalls = new AtomicInteger(0);
    tester
        .getOrCreate(parentKey)
        .setBuilder(
            new SkyFunction() {
              @Nullable
              @Override
              public SkyValue compute(SkyKey skyKey, Environment env)
                  throws SkyFunctionException, InterruptedException {
                numParentComputeCalls.incrementAndGet();
                if (!keepGoing || numParentComputeCalls.get() == 1) {
                  Preconditions.checkState(env.getValue(childKey) == null);
                  Preconditions.checkState(env.getValue(childKey) == null);
                } else {
                  Preconditions.checkState(env.getValue(childKey).equals(childValue));
                  Preconditions.checkState(env.getValue(childKey).equals(childValue));
                }
                throw new GenericFunctionException(parentExn, Transience.PERSISTENT);
              }
            });

    Exception exception = tester.evalAndGetError(keepGoing, parentKey).getException();
    assertThat(exception).isInstanceOf(SomeErrorException.class);
    assertThat(exception).hasMessageThat().isEqualTo("bad");
  }

  /** Data encapsulating a graph inconsistency found during evaluation. */
  @AutoValue
  abstract static class InconsistencyData {
    abstract SkyKey key();

    abstract ImmutableSet<SkyKey> otherKeys();

    abstract Inconsistency inconsistency();

    static InconsistencyData resetRequested(SkyKey key) {
      return create(key, /* otherKeys= */ null, Inconsistency.RESET_REQUESTED);
    }

    static InconsistencyData rewind(SkyKey parent, ImmutableSet<SkyKey> children) {
      return create(parent, children, Inconsistency.PARENT_FORCE_REBUILD_OF_CHILD);
    }

    static InconsistencyData create(
        SkyKey key, @Nullable Collection<SkyKey> otherKeys, Inconsistency inconsistency) {
      return new AutoValue_MemoizingEvaluatorTest_InconsistencyData(
          key,
          otherKeys == null ? ImmutableSet.of() : ImmutableSet.copyOf(otherKeys),
          inconsistency);
    }
  }

  /** A graph tester that is specific to the memoizing evaluator, with some convenience methods. */
  protected final class MemoizingEvaluatorTester extends GraphTester {
    private RecordingDifferencer differencer;
    private MemoizingEvaluator evaluator;
    private TrackingProgressReceiver progressReceiver =
        createTrackingProgressReceiver(/*checkEvaluationResults=*/ true);
    private GraphInconsistencyReceiver graphInconsistencyReceiver =
        GraphInconsistencyReceiver.THROWING;
    private EventFilter eventFilter = EventFilter.FULL_STORAGE;

    /** Constructs a new {@link #evaluator}, so call before injecting a transformer into it! */
    public void initialize() {
      this.differencer = getRecordingDifferencer();
      this.evaluator =
          getMemoizingEvaluator(
              getSkyFunctionMap(),
              differencer,
              progressReceiver,
              graphInconsistencyReceiver,
              eventFilter);
    }

    /**
     * Sets the {@link #progressReceiver}. {@link #initialize} must be called after this to have any
     * effect.
     */
    public void setProgressReceiver(TrackingProgressReceiver progressReceiver) {
      this.progressReceiver = progressReceiver;
    }

    /**
     * Sets the {@link #eventFilter}. {@link #initialize} must be called after this to have any
     * effect.
     */
    public void setEventFilter(EventFilter eventFilter) {
      this.eventFilter = eventFilter;
    }

    /**
     * Sets the {@link #graphInconsistencyReceiver}. {@link #initialize} must be called after this
     * to have any effect.
     */
    public void setGraphInconsistencyReceiver(
        GraphInconsistencyReceiver graphInconsistencyReceiver) {
      this.graphInconsistencyReceiver = graphInconsistencyReceiver;
    }

    public MemoizingEvaluator getEvaluator() {
      return evaluator;
    }

    public void invalidate() throws InterruptedException {
      evaluator.noteEvaluationsAtSameVersionMayBeFinished(reporter);
      differencer.invalidate(getModifiedValues());
      clearModifiedValues();
      progressReceiver.clear();
    }

    public void invalidateTransientErrors() {
      differencer.invalidateTransientErrors();
    }

    public void delete(String key) {
      evaluator.delete(Predicates.equalTo(skyKey(key)));
    }

    public void resetPlayedEvents() {
      emittedEventState.clear();
    }

    public Set<SkyKey> getDirtyKeys() {
      return progressReceiver.dirty;
    }

    public Set<SkyKey> getDeletedKeys() {
      return progressReceiver.deleted;
    }

    public Set<SkyKey> getEnqueuedValues() {
      return progressReceiver.enqueued;
    }

    public <T extends SkyValue> EvaluationResult<T> eval(
        boolean keepGoing, int numThreads, SkyKey... keys) throws InterruptedException {
      assertThat(getModifiedValues()).isEmpty();
      EvaluationContext evaluationContext =
          EvaluationContext.newBuilder()
              .setKeepGoing(keepGoing)
              .setParallelism(numThreads)
              .setEventHandler(reporter)
              .build();
      BugReport.maybePropagateLastCrashIfInTest();
      EvaluationResult<T> result = null;
      beforeEvaluation();
      try {
        result = evaluator.evaluate(ImmutableList.copyOf(keys), evaluationContext);
        return result;
      } finally {
        afterEvaluation(result, evaluationContext);
      }
    }

    public <T extends SkyValue> EvaluationResult<T> eval(boolean keepGoing, SkyKey... keys)
        throws InterruptedException {
      return eval(keepGoing, 100, keys);
    }

    public <T extends SkyValue> EvaluationResult<T> eval(boolean keepGoing, String... keys)
        throws InterruptedException {
      return eval(keepGoing, toSkyKeys(keys).toArray(new SkyKey[0]));
    }

    public SkyValue evalAndGet(boolean keepGoing, String key) throws InterruptedException {
      return evalAndGet(keepGoing, skyKey(key));
    }

    public SkyValue evalAndGet(String key) throws InterruptedException {
      return evalAndGet(/*keepGoing=*/ false, key);
    }

    public SkyValue evalAndGet(boolean keepGoing, SkyKey key) throws InterruptedException {
      EvaluationResult<StringValue> evaluationResult = eval(keepGoing, key);
      SkyValue result = evaluationResult.get(key);
      assertWithMessage(evaluationResult.toString()).that(result).isNotNull();
      return result;
    }

    public ErrorInfo evalAndGetError(boolean keepGoing, SkyKey key) throws InterruptedException {
      EvaluationResult<StringValue> evaluationResult = eval(keepGoing, key);
      assertThatEvaluationResult(evaluationResult).hasErrorEntryForKeyThat(key);
      return evaluationResult.getError(key);
    }

    public ErrorInfo evalAndGetError(boolean keepGoing, String key) throws InterruptedException {
      return evalAndGetError(keepGoing, skyKey(key));
    }

    @Nullable
    public SkyValue getExistingValue(SkyKey key) throws InterruptedException {
      return evaluator.getExistingValue(key);
    }

    @Nullable
    public SkyValue getExistingValue(String key) throws InterruptedException {
      return getExistingValue(skyKey(key));
    }
  }
}
