// Copyright 2016 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.devtools.build.skyframe.ParallelEvaluator.isDoneForBuild;
import static com.google.devtools.build.skyframe.ParallelEvaluator.maybeGetValueFromError;

import com.google.common.base.Function;
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.collect.Maps;
import com.google.common.collect.Sets;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.util.GroupedList;
import com.google.devtools.build.lib.util.GroupedList.GroupedListHelper;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.skyframe.EvaluationProgressReceiver.EvaluationState;
import com.google.devtools.build.skyframe.NodeEntry.DependencyState;
import com.google.devtools.build.skyframe.ParallelEvaluatorContext.EnqueueParentBehavior;
import com.google.devtools.build.skyframe.QueryableGraph.Reason;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import javax.annotation.Nullable;

/** A {@link SkyFunction.Environment} implementation for {@link ParallelEvaluator}. */
class SkyFunctionEnvironment extends AbstractSkyFunctionEnvironment {
  private static final SkyValue NULL_MARKER = new SkyValue() {};
  private static final boolean PREFETCH_OLD_DEPS =
      Boolean.parseBoolean(
          System.getProperty("skyframe.ParallelEvaluator.PrefetchOldDeps", "true"));

  private boolean building = true;
  private SkyKey depErrorKey = null;
  private final SkyKey skyKey;
  /**
   * The deps requested during the previous build of this node. Used for two reasons: (1) They are
   * fetched eagerly before the node is built, to potentially prime the graph and speed up requests
   * for them during evaluation. (2) When the node finishes building, any deps from the previous
   * build that are not deps from this build must have this node removed from them as a reverse dep.
   * Thus, it is important that all nodes in this set have the property that they have this node as
   * a reverse dep from the last build, but that this node has not added them as a reverse dep on
   * this build. That set is normally {@link NodeEntry#getAllRemainingDirtyDirectDeps()}, but in
   * certain corner cases, like cycles, further filtering may be needed.
   */
  private final Set<SkyKey> oldDeps;

  private SkyValue value = null;
  private ErrorInfo errorInfo = null;
  private final Map<SkyKey, ValueWithMetadata> bubbleErrorInfo;
  /** The values previously declared as dependencies. */
  private final Map<SkyKey, NodeEntry> directDeps;

  /**
   * The grouped list of values requested during this build as dependencies. On a subsequent build,
   * if this value is dirty, all deps in the same dependency group can be checked in parallel for
   * changes. In other words, if dep1 and dep2 are in the same group, then dep1 will be checked in
   * parallel with dep2. See {@link #getValues} for more.
   */
  private final GroupedListHelper<SkyKey> newlyRequestedDeps = new GroupedListHelper<>();

  /** The set of errors encountered while fetching children. */
  private final Collection<ErrorInfo> childErrorInfos = new LinkedHashSet<>();

  private final StoredEventHandler eventHandler =
      new StoredEventHandler() {
        @Override
        @SuppressWarnings("UnsynchronizedOverridesSynchronized") // only delegates to thread-safe.
        public void handle(Event e) {
          checkActive();
          if (evaluatorContext.getStoredEventFilter().apply(e)) {
            super.handle(e);
          } else {
            evaluatorContext.getReporter().handle(e);
          }
        }

        @Override
        @SuppressWarnings("UnsynchronizedOverridesSynchronized") // only delegates to thread-safe.
        public void post(ExtendedEventHandler.Postable e) {
          if (e instanceof ExtendedEventHandler.ProgressLike) {
            evaluatorContext.getReporter().post(e);
          } else {
            super.post(e);
          }
        }
      };
  private final ParallelEvaluatorContext evaluatorContext;

  SkyFunctionEnvironment(
      SkyKey skyKey,
      GroupedList<SkyKey> directDeps,
      Set<SkyKey> oldDeps,
      ParallelEvaluatorContext evaluatorContext)
      throws InterruptedException {
    this(skyKey, directDeps, null, oldDeps, evaluatorContext);
  }

  SkyFunctionEnvironment(
      SkyKey skyKey,
      GroupedList<SkyKey> directDeps,
      @Nullable Map<SkyKey, ValueWithMetadata> bubbleErrorInfo,
      Set<SkyKey> oldDeps,
      ParallelEvaluatorContext evaluatorContext)
      throws InterruptedException {
    this.skyKey = skyKey;
    this.oldDeps = oldDeps;
    this.evaluatorContext = evaluatorContext;
    this.directDeps =
        Collections.<SkyKey, NodeEntry>unmodifiableMap(
            batchPrefetch(
                skyKey, directDeps, oldDeps, /*assertDone=*/ bubbleErrorInfo == null, skyKey));
    this.bubbleErrorInfo = bubbleErrorInfo;
    Preconditions.checkState(
        !this.directDeps.containsKey(ErrorTransienceValue.KEY),
        "%s cannot have a dep on ErrorTransienceValue during building",
        skyKey);
  }

  private Map<SkyKey, ? extends NodeEntry> batchPrefetch(
      SkyKey requestor,
      GroupedList<SkyKey> depKeys,
      Set<SkyKey> oldDeps,
      boolean assertDone,
      SkyKey keyForDebugging)
      throws InterruptedException {
    Iterable<SkyKey> depKeysAsIterable = Iterables.concat(depKeys);
    Iterable<SkyKey> keysToPrefetch = depKeysAsIterable;
    if (PREFETCH_OLD_DEPS) {
      ImmutableSet.Builder<SkyKey> keysToPrefetchBuilder = ImmutableSet.builder();
      keysToPrefetchBuilder.addAll(depKeysAsIterable).addAll(oldDeps);
      keysToPrefetch = keysToPrefetchBuilder.build();
    }
    Map<SkyKey, ? extends NodeEntry> batchMap =
        evaluatorContext.getBatchValues(requestor, Reason.PREFETCH, keysToPrefetch);
    if (PREFETCH_OLD_DEPS) {
      batchMap =
          ImmutableMap.<SkyKey, NodeEntry>copyOf(
              Maps.filterKeys(batchMap, Predicates.in(ImmutableSet.copyOf(depKeysAsIterable))));
    }
    if (batchMap.size() != depKeys.numElements()) {
      throw new IllegalStateException(
          "Missing keys for "
              + keyForDebugging
              + ": "
              + Sets.difference(depKeys.toSet(), batchMap.keySet()));
    }
    if (assertDone) {
      for (Map.Entry<SkyKey, ? extends NodeEntry> entry : batchMap.entrySet()) {
        Preconditions.checkState(
            entry.getValue().isDone(), "%s had not done %s", keyForDebugging, entry);
      }
    }
    return batchMap;
  }

  private void checkActive() {
    Preconditions.checkState(building, skyKey);
  }

  NestedSet<TaggedEvents> buildEvents(NodeEntry entry, boolean missingChildren)
      throws InterruptedException {
    // Aggregate the nested set of events from the direct deps, also adding the events from
    // building this value.
    NestedSetBuilder<TaggedEvents> eventBuilder = NestedSetBuilder.stableOrder();
    ImmutableList<Event> events = eventHandler.getEvents();
    if (!events.isEmpty()) {
      eventBuilder.add(new TaggedEvents(getTagFromKey(), events));
    }
    if (evaluatorContext.getStoredEventFilter().storeEvents()) {
      // Only do the work of processing children if we're going to store events.
      GroupedList<SkyKey> depKeys = entry.getTemporaryDirectDeps();
      Collection<SkyValue> deps = getDepValuesForDoneNodeMaybeFromError(depKeys);
      if (!missingChildren && depKeys.numElements() != deps.size()) {
        throw new IllegalStateException(
            "Missing keys for "
                + skyKey
                + ". Present values: "
                + deps
                + " requested from: "
                + depKeys
                + ", "
                + entry);
      }
      for (SkyValue value : deps) {
        eventBuilder.addTransitive(ValueWithMetadata.getEvents(value));
      }
    }
    return eventBuilder.build();
  }

  /**
   * If this node has an error, that is, if errorInfo is non-null, do nothing. Otherwise, set
   * errorInfo to the union of the child errors that were recorded earlier by getValueOrException,
   * if there are any.
   *
   * <p>Child errors are remembered, if there are any and yet the parent recovered without error, so
   * that subsequent noKeepGoing evaluations can stop as soon as they encounter a node whose
   * (transitive) children had experienced an error, even if that (transitive) parent node had been
   * able to recover from it during a keepGoing build. This behavior can be suppressed by setting
   * {@link ParallelEvaluatorContext#storeErrorsAlongsideValues} to false, which will cause nodes
   * with values to have no stored error info. This may be useful if this graph will only ever be
   * used for keepGoing builds, since in that case storing errors from recovered nodes is pointless.
   */
  private void finalizeErrorInfo() {
    if (errorInfo == null
        && (evaluatorContext.storeErrorsAlongsideValues() || value == null)
        && !childErrorInfos.isEmpty()) {
      errorInfo = ErrorInfo.fromChildErrors(skyKey, childErrorInfos);
    }
  }

  void setValue(SkyValue newValue) {
    Preconditions.checkState(
        errorInfo == null && bubbleErrorInfo == null,
        "%s %s %s %s",
        skyKey,
        newValue,
        errorInfo,
        bubbleErrorInfo);
    Preconditions.checkState(value == null, "%s %s %s", skyKey, value, newValue);
    value = newValue;
  }

  /**
   * Set this node to be in error. The node's value must not have already been set. However, all
   * dependencies of this node <i>must</i> already have been registered, since this method may
   * register a dependence on the error transience node, which should always be the last dep.
   */
  void setError(NodeEntry state, ErrorInfo errorInfo, boolean isDirectlyTransient)
      throws InterruptedException {
    Preconditions.checkState(value == null, "%s %s %s", skyKey, value, errorInfo);
    Preconditions.checkState(this.errorInfo == null, "%s %s %s", skyKey, this.errorInfo, errorInfo);

    if (isDirectlyTransient) {
      NodeEntry errorTransienceNode =
          Preconditions.checkNotNull(
              evaluatorContext
                  .getGraph()
                  .get(skyKey, Reason.RDEP_ADDITION, ErrorTransienceValue.KEY),
              "Null error value? %s",
              skyKey);
      DependencyState triState;
      if (oldDeps.contains(ErrorTransienceValue.KEY)) {
        triState = errorTransienceNode.checkIfDoneForDirtyReverseDep(skyKey);
      } else {
        triState = errorTransienceNode.addReverseDepAndCheckIfDone(skyKey);
      }
      Preconditions.checkState(
          triState == DependencyState.DONE, "%s %s %s", skyKey, triState, errorInfo);
      state.addTemporaryDirectDeps(GroupedListHelper.create(ErrorTransienceValue.KEY));
      state.signalDep();
    }

    this.errorInfo = Preconditions.checkNotNull(errorInfo, skyKey);
  }

  private Map<SkyKey, SkyValue> getValuesMaybeFromError(Iterable<SkyKey> keys)
      throws InterruptedException {
    // Use a HashMap, not an ImmutableMap.Builder, because we have not yet deduplicated these keys
    // and ImmutableMap.Builder does not tolerate duplicates.  The map will be thrown away
    // shortly in any case.
    Map<SkyKey, SkyValue> result = new HashMap<>();
    ArrayList<SkyKey> missingKeys = new ArrayList<>();
    for (SkyKey key : keys) {
      Preconditions.checkState(
          !key.equals(ErrorTransienceValue.KEY),
          "Error transience key cannot be in requested deps of %s",
          skyKey);
      SkyValue value = maybeGetValueFromErrorOrDeps(key);
      if (value == null) {
        missingKeys.add(key);
      } else {
        result.put(key, value);
      }
    }
    Map<SkyKey, ? extends NodeEntry> missingEntries =
        evaluatorContext.getBatchValues(skyKey, Reason.DEP_REQUESTED, missingKeys);
    for (SkyKey key : missingKeys) {
      result.put(key, getValueOrNullMarker(missingEntries.get(key)));
    }
    return result;
  }

  /**
   * Returns just the values of the deps in {@code depKeys}, looking at {@code bubbleErrorInfo},
   * {@link #directDeps}, and the backing {@link #evaluatorContext#graph} in that order. Any deps
   * that are not yet done will not have their values present in the returned collection.
   */
  private Collection<SkyValue> getDepValuesForDoneNodeMaybeFromError(GroupedList<SkyKey> depKeys)
      throws InterruptedException {
    int keySize = depKeys.numElements();
    List<SkyValue> result = new ArrayList<>(keySize);
    // depKeys consists of all known deps of this entry. That should include all the keys in
    // directDeps, and any keys in bubbleErrorInfo. We expect to have to retrieve the keys that
    // are not in either one.
    int expectedMissingKeySize =
        Math.max(
            keySize - directDeps.size() - (bubbleErrorInfo == null ? 0 : bubbleErrorInfo.size()),
            0);
    ArrayList<SkyKey> missingKeys = new ArrayList<>(expectedMissingKeySize);
    for (SkyKey key : Iterables.concat(depKeys)) {
      SkyValue value = maybeGetValueFromErrorOrDeps(key);
      if (value == null) {
        missingKeys.add(key);
      } else {
        result.add(value);
      }
    }
    for (NodeEntry entry :
        evaluatorContext.getBatchValues(skyKey, Reason.DEP_REQUESTED, missingKeys).values()) {
      result.add(getValueOrNullMarker(entry));
    }
    return result;
  }

  @Nullable
  private SkyValue maybeGetValueFromErrorOrDeps(SkyKey key) throws InterruptedException {
    return maybeGetValueFromError(key, directDeps.get(key), bubbleErrorInfo);
  }

  private static SkyValue getValueOrNullMarker(@Nullable NodeEntry nodeEntry)
      throws InterruptedException {
    return isDoneForBuild(nodeEntry) ? nodeEntry.getValueMaybeWithMetadata() : NULL_MARKER;
  }

  @Override
  protected Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(
      Iterable<SkyKey> depKeys) throws InterruptedException {
    checkActive();
    Map<SkyKey, SkyValue> values = getValuesMaybeFromError(depKeys);
    for (Map.Entry<SkyKey, SkyValue> depEntry : values.entrySet()) {
      SkyKey depKey = depEntry.getKey();
      SkyValue depValue = depEntry.getValue();
      if (depValue == NULL_MARKER) {
        if (directDeps.containsKey(depKey)) {
          throw new IllegalStateException(
              "Undone key "
                  + depKey
                  + " was already in deps of "
                  + skyKey
                  + "( dep: "
                  + evaluatorContext.getGraph().get(skyKey, Reason.OTHER, depKey)
                  + ", parent: "
                  + evaluatorContext.getGraph().get(null, Reason.OTHER, skyKey));
        }
        valuesMissing = true;
        addDep(depKey);
        continue;
      }
      ErrorInfo errorInfo = ValueWithMetadata.getMaybeErrorInfo(depEntry.getValue());
      if (errorInfo != null) {
        childErrorInfos.add(errorInfo);
        if (bubbleErrorInfo != null) {
          // Set interrupted status, to try to prevent the calling SkyFunction from doing anything
          // fancy after this. SkyFunctions executed during error bubbling are supposed to
          // (quickly) rethrow errors or return a value/null (but there's currently no way to
          // enforce this).
          Thread.currentThread().interrupt();
        }
        if ((!evaluatorContext.keepGoing() && bubbleErrorInfo == null)
            || errorInfo.getException() == null) {
          valuesMissing = true;
          // We arbitrarily record the first child error if we are about to abort.
          if (!evaluatorContext.keepGoing() && depErrorKey == null) {
            depErrorKey = depKey;
          }
        }
      }

      if (!directDeps.containsKey(depKey)) {
        if (bubbleErrorInfo == null) {
          addDep(depKey);
        }
        evaluatorContext
            .getReplayingNestedSetEventVisitor()
            .visit(ValueWithMetadata.getEvents(depValue));
      }
    }

    return Maps.transformValues(
        values,
        new Function<SkyValue, ValueOrUntypedException>() {
          @Override
          public ValueOrUntypedException apply(SkyValue maybeWrappedValue) {
            if (maybeWrappedValue == NULL_MARKER) {
              return ValueOrExceptionUtils.ofNull();
            }
            SkyValue justValue = ValueWithMetadata.justValue(maybeWrappedValue);
            ErrorInfo errorInfo = ValueWithMetadata.getMaybeErrorInfo(maybeWrappedValue);

            if (justValue != null && (evaluatorContext.keepGoing() || errorInfo == null)) {
              // If the dep did compute a value, it is given to the caller if we are in
              // keepGoing mode or if we are in noKeepGoingMode and there were no errors computing
              // it.
              return ValueOrExceptionUtils.ofValueUntyped(justValue);
            }

            // There was an error building the value, which we will either report by throwing an
            // exception or insulate the caller from by returning null.
            Preconditions.checkNotNull(errorInfo, "%s %s", skyKey, maybeWrappedValue);
            Exception exception = errorInfo.getException();

            if (!evaluatorContext.keepGoing() && exception != null && bubbleErrorInfo == null) {
              // Child errors should not be propagated in noKeepGoing mode (except during error
              // bubbling). Instead we should fail fast.
              return ValueOrExceptionUtils.ofNull();
            }

            if (exception != null) {
              // Give builder a chance to handle this exception.
              return ValueOrExceptionUtils.ofExn(exception);
            }
            // In a cycle.
            Preconditions.checkState(
                !Iterables.isEmpty(errorInfo.getCycleInfo()),
                "%s %s %s",
                skyKey,
                errorInfo,
                maybeWrappedValue);
            return ValueOrExceptionUtils.ofNull();
          }
        });
  }

  @Override
  public <
          E1 extends Exception,
          E2 extends Exception,
          E3 extends Exception,
          E4 extends Exception,
          E5 extends Exception>
      Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> getValuesOrThrow(
          Iterable<SkyKey> depKeys,
          Class<E1> exceptionClass1,
          Class<E2> exceptionClass2,
          Class<E3> exceptionClass3,
          Class<E4> exceptionClass4,
          Class<E5> exceptionClass5)
          throws InterruptedException {
    newlyRequestedDeps.startGroup();
    Map<SkyKey, ValueOrException5<E1, E2, E3, E4, E5>> result =
        super.getValuesOrThrow(
            depKeys,
            exceptionClass1,
            exceptionClass2,
            exceptionClass3,
            exceptionClass4,
            exceptionClass5);
    newlyRequestedDeps.endGroup();
    return result;
  }

  private void addDep(SkyKey key) {
    newlyRequestedDeps.add(key);
  }

  /**
   * If {@code !keepGoing} and there is at least one dep in error, returns a dep in error. Otherwise
   * returns {@code null}.
   */
  @Nullable
  SkyKey getDepErrorKey() {
    return depErrorKey;
  }

  @Override
  public ExtendedEventHandler getListener() {
    checkActive();
    return eventHandler;
  }

  void doneBuilding() {
    building = false;
  }

  GroupedListHelper<SkyKey> getNewlyRequestedDeps() {
    return newlyRequestedDeps;
  }

  Collection<NodeEntry> getDirectDepsValues() {
    return directDeps.values();
  }

  Collection<ErrorInfo> getChildErrorInfos() {
    return childErrorInfos;
  }

  /**
   * Apply the change to the graph (mostly) atomically and signal all nodes that are waiting for
   * this node to complete. Adding nodes and signaling is not atomic, but may need to be changed for
   * interruptibility.
   *
   * <p>Parents are only enqueued if {@code enqueueParents} holds. Parents should be enqueued unless
   * (1) this node is being built after the main evaluation has aborted, or (2) this node is being
   * built with --nokeep_going, and so we are about to shut down the main evaluation anyway.
   *
   * <p>The node entry is informed if the node's value and error are definitive via the flag {@code
   * completeValue}.
   */
  void commit(NodeEntry primaryEntry, EnqueueParentBehavior enqueueParents)
      throws InterruptedException {
    // Construct the definitive error info, if there is one.
    finalizeErrorInfo();

    // We have the following implications:
    // errorInfo == null => value != null => enqueueParents.
    // All these implications are strict:
    // (1) errorInfo != null && value != null happens for values with recoverable errors.
    // (2) value == null && enqueueParents happens for values that are found to have errors
    // during a --keep_going build.

    NestedSet<TaggedEvents> events = buildEvents(primaryEntry, /*missingChildren=*/ false);
    Version valueVersion;
    SkyValue valueWithMetadata;
    if (value == null) {
      Preconditions.checkNotNull(errorInfo, "%s %s", skyKey, primaryEntry);
      valueWithMetadata = ValueWithMetadata.error(errorInfo, events);
    } else {
      // We must be enqueueing parents if we have a value.
      Preconditions.checkState(
          enqueueParents == EnqueueParentBehavior.ENQUEUE, "%s %s", skyKey, primaryEntry);
      valueWithMetadata = ValueWithMetadata.normal(value, errorInfo, events);
    }
    if (!oldDeps.isEmpty()) {
      // Remove the rdep on this entry for each of its old deps that is no longer a direct dep.
      Set<SkyKey> depsToRemove =
          Sets.difference(oldDeps, primaryEntry.getTemporaryDirectDeps().toSet());
      Collection<? extends NodeEntry> oldDepEntries =
          evaluatorContext.getGraph().getBatch(skyKey, Reason.RDEP_REMOVAL, depsToRemove).values();
      for (NodeEntry oldDepEntry : oldDepEntries) {
        oldDepEntry.removeReverseDep(skyKey);
      }
    }
    // If this entry is dirty, setValue may not actually change it, if it determines that
    // the data being written now is the same as the data already present in the entry.
    // We could consider using max(childVersions) here instead of graphVersion. When full
    // versioning is implemented, this would allow evaluation at a version between
    // max(childVersions) and graphVersion to re-use this result.
    Set<SkyKey> reverseDeps =
        primaryEntry.setValue(valueWithMetadata, evaluatorContext.getGraphVersion());
    // Note that if this update didn't actually change the value entry, this version may not
    // be the graph version.
    valueVersion = primaryEntry.getVersion();
    Preconditions.checkState(
        valueVersion.atMost(evaluatorContext.getGraphVersion()),
        "%s should be at most %s in the version partial ordering",
        valueVersion,
        evaluatorContext.getGraphVersion());

    // Tell the receiver that this value was built. If valueVersion.equals(graphVersion), it was
    // evaluated this run, and so was changed. Otherwise, it is less than graphVersion, by the
    // Preconditions check above, and was not actually changed this run -- when it was written
    // above, its version stayed below this update's version, so its value remains the same.
    // We use a SkyValueSupplier here because it keeps a reference to the entry, allowing for
    // the receiver to be confident that the entry is readily accessible in memory.
    evaluatorContext
        .getProgressReceiver()
        .evaluated(
            skyKey,
            new SkyValueSupplier(primaryEntry),
            valueVersion.equals(evaluatorContext.getGraphVersion())
                ? EvaluationState.BUILT
                : EvaluationState.CLEAN);

    evaluatorContext.signalValuesAndEnqueueIfReady(
        skyKey, reverseDeps, valueVersion, enqueueParents);

    evaluatorContext.getReplayingNestedSetEventVisitor().visit(events);
  }

  @Nullable
  private String getTagFromKey() {
    return evaluatorContext.getSkyFunctions().get(skyKey.functionName()).extractTag(skyKey);
  }

  /**
   * Gets the latch that is counted down when an exception is thrown in {@code
   * AbstractQueueVisitor}. For use in tests to check if an exception actually was thrown. Calling
   * {@code AbstractQueueVisitor#awaitExceptionForTestingOnly} can throw a spurious {@link
   * InterruptedException} because {@link CountDownLatch#await} checks the interrupted bit before
   * returning, even if the latch is already at 0. See bug "testTwoErrors is flaky".
   */
  CountDownLatch getExceptionLatchForTesting() {
    return evaluatorContext.getVisitor().getExceptionLatchForTestingOnly();
  }

  @Override
  public boolean inErrorBubblingForTesting() {
    return bubbleErrorInfo != null;
  }
}
