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

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.common.collect.Streams.stream;
import static com.google.common.truth.Truth.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
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.Lists;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.actions.AbstractAction;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionAnalysisMetadata;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
import com.google.devtools.build.lib.actions.ActionExecutionContext.LostInputsCheck;
import com.google.devtools.build.lib.actions.ActionGraph;
import com.google.devtools.build.lib.actions.ActionInput;
import com.google.devtools.build.lib.actions.ActionInputPrefetcher;
import com.google.devtools.build.lib.actions.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionLookupData;
import com.google.devtools.build.lib.actions.ActionLookupKey;
import com.google.devtools.build.lib.actions.ActionOwner;
import com.google.devtools.build.lib.actions.ActionResult;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
import com.google.devtools.build.lib.actions.Artifact.DerivedArtifact;
import com.google.devtools.build.lib.actions.Artifact.SourceArtifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifact;
import com.google.devtools.build.lib.actions.Artifact.SpecialArtifactType;
import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
import com.google.devtools.build.lib.actions.ArtifactOwner;
import com.google.devtools.build.lib.actions.ArtifactResolver;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.ArtifactRoot.RootType;
import com.google.devtools.build.lib.actions.BuildConfigurationEvent;
import com.google.devtools.build.lib.actions.DiscoveredModulesPruner;
import com.google.devtools.build.lib.actions.Executor;
import com.google.devtools.build.lib.actions.FileArtifactValue;
import com.google.devtools.build.lib.actions.MiddlemanType;
import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
import com.google.devtools.build.lib.actions.PackageRootResolver;
import com.google.devtools.build.lib.actions.ThreadStateReceiver;
import com.google.devtools.build.lib.actions.cache.MetadataHandler;
import com.google.devtools.build.lib.actions.cache.Protos.ActionCacheStatistics.MissDetail;
import com.google.devtools.build.lib.actions.cache.Protos.ActionCacheStatistics.MissReason;
import com.google.devtools.build.lib.actions.cache.VirtualActionInput;
import com.google.devtools.build.lib.analysis.actions.CustomCommandLine;
import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.buildeventstream.BuildEventStreamProtos;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.RepositoryName;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.collect.nestedset.Order;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.exec.SingleBuildFileCache;
import com.google.devtools.build.lib.skyframe.ActionTemplateExpansionValue;
import com.google.devtools.build.lib.skyframe.ActionTemplateExpansionValue.ActionTemplateExpansionKey;
import com.google.devtools.build.lib.skyframe.BuildConfigurationKey;
import com.google.devtools.build.lib.skyframe.TreeArtifactValue;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.SerializationConstant;
import com.google.devtools.build.lib.util.FileType;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.util.ResourceUsage;
import com.google.devtools.build.lib.util.io.FileOutErr;
import com.google.devtools.build.lib.vfs.DigestHashFunction;
import com.google.devtools.build.lib.vfs.FileStatus;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.SyscallCache;
import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem;
import com.google.devtools.build.skyframe.AbstractSkyFunctionEnvironment;
import com.google.devtools.build.skyframe.ErrorInfo;
import com.google.devtools.build.skyframe.EvaluationContext;
import com.google.devtools.build.skyframe.EvaluationResult;
import com.google.devtools.build.skyframe.MemoizingEvaluator;
import com.google.devtools.build.skyframe.SkyFunction;
import com.google.devtools.build.skyframe.SkyFunctionName;
import com.google.devtools.build.skyframe.SkyKey;
import com.google.devtools.build.skyframe.SkyValue;
import com.google.devtools.build.skyframe.ValueOrUntypedException;
import com.google.devtools.build.skyframe.Version;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import net.starlark.java.syntax.Location;

/** A bunch of utilities that are useful for tests concerning actions, artifacts, etc. */
public final class ActionsTestUtil {

  private final ActionGraph actionGraph;

  public ActionsTestUtil(ActionGraph actionGraph) {
    this.actionGraph = actionGraph;
  }

  private static final Label NULL_LABEL = Label.parseAbsoluteUnchecked("//null/action:owner");

  public static ActionExecutionContext createContext(
      Executor executor,
      ExtendedEventHandler eventHandler,
      ActionKeyContext actionKeyContext,
      FileOutErr fileOutErr,
      Path execRoot,
      MetadataHandler metadataHandler) {
    return createContext(
        executor,
        eventHandler,
        actionKeyContext,
        fileOutErr,
        execRoot,
        metadataHandler,
        /*clientEnv=*/ ImmutableMap.of());
  }

  public static ActionExecutionContext createContext(
      Executor executor,
      ExtendedEventHandler eventHandler,
      ActionKeyContext actionKeyContext,
      FileOutErr fileOutErr,
      Path execRoot,
      MetadataHandler metadataHandler,
      Map<String, String> clientEnv) {
    return new ActionExecutionContext(
        executor,
        new SingleBuildFileCache(
            execRoot.getPathString(), execRoot.getFileSystem(), SyscallCache.NO_CACHE),
        ActionInputPrefetcher.NONE,
        actionKeyContext,
        metadataHandler,
        /*rewindingEnabled=*/ false,
        LostInputsCheck.NONE,
        fileOutErr,
        eventHandler,
        ImmutableMap.copyOf(clientEnv),
        /*topLevelFilesets=*/ ImmutableMap.of(),
        (artifact, output) -> {},
        /*actionFileSystem=*/ null,
        /*skyframeDepsResult=*/ null,
        DiscoveredModulesPruner.DEFAULT,
        SyscallCache.NO_CACHE,
        ThreadStateReceiver.NULL_INSTANCE);
  }

  public static ActionExecutionContext createContext(ExtendedEventHandler eventHandler) {
    return createContext(new DummyExecutor(), eventHandler);
  }

  public static ActionExecutionContext createContext(
      Executor executor, ExtendedEventHandler eventHandler) {
    return new ActionExecutionContext(
        executor,
        /*actionInputFileCache=*/ null,
        ActionInputPrefetcher.NONE,
        new ActionKeyContext(),
        /*metadataHandler=*/ null,
        /*rewindingEnabled=*/ false,
        LostInputsCheck.NONE,
        /*fileOutErr=*/ null,
        eventHandler,
        /*clientEnv=*/ ImmutableMap.of(),
        /*topLevelFilesets=*/ ImmutableMap.of(),
        (artifact, output) -> {},
        /*actionFileSystem=*/ null,
        /*skyframeDepsResult=*/ null,
        DiscoveredModulesPruner.DEFAULT,
        SyscallCache.NO_CACHE,
        ThreadStateReceiver.NULL_INSTANCE);
  }

  public static ActionExecutionContext createContextForInputDiscovery(
      Executor executor,
      ExtendedEventHandler eventHandler,
      ActionKeyContext actionKeyContext,
      FileOutErr fileOutErr,
      Path execRoot,
      MetadataHandler metadataHandler,
      MemoizingEvaluator evaluator,
      DiscoveredModulesPruner discoveredModulesPruner) {
    return ActionExecutionContext.forInputDiscovery(
        executor,
        new SingleBuildFileCache(
            execRoot.getPathString(), execRoot.getFileSystem(), SyscallCache.NO_CACHE),
        ActionInputPrefetcher.NONE,
        actionKeyContext,
        metadataHandler,
        /*rewindingEnabled=*/ false,
        LostInputsCheck.NONE,
        fileOutErr,
        eventHandler,
        ImmutableMap.of(),
        new BlockingSkyFunctionEnvironment(evaluator, eventHandler),
        /*actionFileSystem=*/ null,
        discoveredModulesPruner,
        SyscallCache.NO_CACHE,
        ThreadStateReceiver.NULL_INSTANCE);
  }

  public static Artifact createArtifact(ArtifactRoot root, Path path) {
    return createArtifactWithRootRelativePath(root, root.getRoot().relativize(path));
  }

  public static Artifact createArtifact(ArtifactRoot root, String path) {
    return createArtifactWithRootRelativePath(root, PathFragment.create(path));
  }

  public static Artifact createArtifactWithRootRelativePath(
      ArtifactRoot root, PathFragment rootRelativePath) {
    PathFragment execPath = root.getExecPath().getRelative(rootRelativePath);
    return createArtifactWithExecPath(root, execPath);
  }

  public static Artifact createArtifactWithExecPath(ArtifactRoot root, PathFragment execPath) {
    return root.isSourceRoot()
        ? new Artifact.SourceArtifact(root, execPath, ArtifactOwner.NULL_OWNER)
        : DerivedArtifact.create(root, execPath, NULL_ARTIFACT_OWNER);
  }

  public static SpecialArtifact createTreeArtifactWithGeneratingAction(
      ArtifactRoot root, PathFragment execPath) {
    SpecialArtifact treeArtifact =
        SpecialArtifact.create(root, execPath, NULL_ARTIFACT_OWNER, SpecialArtifactType.TREE);
    treeArtifact.setGeneratingActionKey(NULL_ACTION_LOOKUP_DATA);
    return treeArtifact;
  }

  public static void assertNoArtifactEndingWith(RuleConfiguredTarget target, String path) {
    Pattern endPattern = Pattern.compile(path + "$");
    for (ActionAnalysisMetadata action : target.getActions()) {
      for (Artifact output : action.getOutputs()) {
        assertThat(output.getExecPathString()).doesNotMatch(endPattern);
      }
    }
  }

  public static ArtifactRoot createArtifactRootFromTwoPaths(Path root, Path execPath) {
    return ArtifactRoot.asDerivedRoot(root, RootType.Output, execPath.relativeTo(root));
  }

  /**
   * Creates a {@link VirtualActionInput} with given string as contents and provided relative path.
   */
  public static VirtualActionInput createVirtualActionInput(String relativePath, String contents) {
    return createVirtualActionInput(PathFragment.create(relativePath), contents);
  }

  /** Creates a {@link VirtualActionInput} with given string as contents and provided path. */
  public static VirtualActionInput createVirtualActionInput(PathFragment path, String contents) {
    return new VirtualActionInput() {
      @Override
      public ByteString getBytes() throws IOException {
        ByteString.Output out = ByteString.newOutput();
        writeTo(out);
        return out.toByteString();
      }

      @Override
      public String getExecPathString() {
        return path.getPathString();
      }

      @Override
      public PathFragment getExecPath() {
        return path;
      }

      @Override
      public boolean isSymlink() {
        return false;
      }

      @Override
      public void writeTo(OutputStream out) throws IOException {
        out.write(contents.getBytes(UTF_8));
      }
    };
  }

  /**
   * {@link SkyFunction.Environment} that internally makes a full Skyframe evaluate call for the
   * requested keys, blocking until the values are ready.
   */
  private static final class BlockingSkyFunctionEnvironment extends AbstractSkyFunctionEnvironment {
    private final MemoizingEvaluator evaluator;
    private final EventHandler eventHandler;

    private BlockingSkyFunctionEnvironment(
        MemoizingEvaluator evaluator, EventHandler eventHandler) {
      this.evaluator = evaluator;
      this.eventHandler = eventHandler;
    }

    @Override
    protected ValueOrUntypedException getSingleValueOrUntypedException(SkyKey depKey)
        throws InterruptedException {
      return getOrderedValueOrUntypedExceptions(ImmutableList.of(depKey)).get(0);
    }

    @Override
    protected Map<SkyKey, ValueOrUntypedException> getValueOrUntypedExceptions(
        Iterable<? extends SkyKey> depKeys) {
      EvaluationResult<SkyValue> evaluationResult;
      Map<SkyKey, ValueOrUntypedException> result = new HashMap<>();
      try {
        EvaluationContext evaluationContext =
            EvaluationContext.newBuilder()
                .setKeepGoing(false)
                .setNumThreads(ResourceUsage.getAvailableProcessors())
                .setEventHandler(new Reporter(new EventBus(), eventHandler))
                .build();
        evaluationResult = evaluator.evaluate(depKeys, evaluationContext);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        for (SkyKey key : depKeys) {
          result.put(key, ValueOrUntypedException.ofNull());
        }
        return result;
      }
      for (SkyKey key : depKeys) {
        SkyValue value = evaluationResult.get(key);
        if (value != null) {
          result.put(key, ValueOrUntypedException.ofValueUntyped(value));
          continue;
        }
        errorMightHaveBeenFound = true;
        ErrorInfo errorInfo = evaluationResult.getError(key);
        if (errorInfo == null || errorInfo.getException() == null) {
          result.put(key, ValueOrUntypedException.ofNull());
          continue;
        }
        result.put(key, ValueOrUntypedException.ofExn(errorInfo.getException()));
      }
      return result;
    }

    @Override
    protected List<ValueOrUntypedException> getOrderedValueOrUntypedExceptions(
        Iterable<? extends SkyKey> depKeys) {
      Map<SkyKey, ValueOrUntypedException> mapResult = getValueOrUntypedExceptions(depKeys);
      return ImmutableList.copyOf(Iterables.transform(depKeys, mapResult::get));
    }

    @Override
    public ExtendedEventHandler getListener() {
      throw new UnsupportedOperationException();
    }

    @Override
    public void registerDependencies(Iterable<SkyKey> keys) {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean inErrorBubblingForSkyFunctionsThatCanFullyRecoverFromErrors() {
      return false;
    }

    @Override
    public boolean restartPermitted() {
      return false;
    }

    @Override
    public <T extends SkyKeyComputeState> T getState(Supplier<T> stateSupplier) {
      return stateSupplier.get();
    }

    @Override
    @Nullable
    public Version getMaxTransitiveSourceVersionSoFar() {
      throw new UnsupportedOperationException();
    }
  }

  @SerializationConstant
  public static final ActionLookupKey NULL_ARTIFACT_OWNER =
      new ActionLookupKey() {

        @Override
        public SkyFunctionName functionName() {
          return null;
        }

        @Override
        public Label getLabel() {
          return NULL_LABEL;
        }

        @Nullable
        @Override
        public BuildConfigurationKey getConfigurationKey() {
          return null;
        }

        @Override
        public String toString() {
          return "NULL_ARTIFACT_OWNER";
        }
      };

  public static final ActionTemplateExpansionKey NULL_TEMPLATE_EXPANSION_ARTIFACT_OWNER =
      ActionTemplateExpansionValue.key(NULL_ARTIFACT_OWNER, /*actionIndex=*/ 0);

  public static final Artifact DUMMY_ARTIFACT =
      new Artifact.SourceArtifact(
          ArtifactRoot.asSourceRoot(
              Root.absoluteRoot(new InMemoryFileSystem(DigestHashFunction.SHA256))),
          PathFragment.create("/dummy"),
          NULL_ARTIFACT_OWNER);

  public static final ActionOwner NULL_ACTION_OWNER =
      ActionOwner.create(
          NULL_LABEL,
          ImmutableList.of(),
          new Location("dummy-file", 0, 0),
          "dummy-configuration-mnemonic",
          "dummy-kind",
          "dummy-configuration",
          new BuildConfigurationEvent(
              BuildEventStreamProtos.BuildEventId.getDefaultInstance(),
              BuildEventStreamProtos.BuildEvent.getDefaultInstance()),
          null,
          ImmutableMap.of(),
          null);

  @SerializationConstant
  public static final ActionLookupData NULL_ACTION_LOOKUP_DATA =
      ActionLookupData.create(NULL_ARTIFACT_OWNER, 0);

  /** An unchecked exception class for action conflicts. */
  public static class UncheckedActionConflictException extends RuntimeException {
    public UncheckedActionConflictException(ActionConflictException e) {
      super(e);
    }
  }

  /** A dummy Action class for use in tests. */
  public static class NullAction extends AbstractAction {

    public NullAction() {
      super(
          NULL_ACTION_OWNER,
          NestedSetBuilder.emptySet(Order.STABLE_ORDER),
          ImmutableList.of(DUMMY_ARTIFACT));
    }

    public NullAction(ActionOwner owner, Artifact... outputs) {
      super(owner, NestedSetBuilder.emptySet(Order.STABLE_ORDER), ImmutableList.copyOf(outputs));
    }

    public NullAction(Artifact... outputs) {
      super(
          NULL_ACTION_OWNER,
          NestedSetBuilder.emptySet(Order.STABLE_ORDER),
          ImmutableList.copyOf(outputs));
    }

    public NullAction(List<Artifact> inputs, Artifact... outputs) {
      super(
          NULL_ACTION_OWNER,
          NestedSetBuilder.wrap(Order.STABLE_ORDER, inputs),
          ImmutableList.copyOf(outputs));
    }

    @Override
    public ActionResult execute(ActionExecutionContext actionExecutionContext) {
      return ActionResult.EMPTY;
    }

    @Override
    protected void computeKey(
        ActionKeyContext actionKeyContext,
        @Nullable ArtifactExpander artifactExpander,
        Fingerprint fp) {
      fp.addString("action");
    }

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

  /**
   * A mocked action containing the inputs and outputs of the action and determines whether or not
   * the action is a middleman. Used for tests that do not need to execute the action.
   */
  public static class MockAction extends AbstractAction {

    private final boolean middleman;
    private final boolean isShareable;

    public MockAction(Iterable<Artifact> inputs, ImmutableSet<Artifact> outputs) {
      this(inputs, outputs, /*middleman=*/ false, /*isShareable=*/ true);
    }

    public MockAction(
        Iterable<Artifact> inputs, ImmutableSet<Artifact> outputs, boolean middleman) {
      this(inputs, outputs, middleman, /*isShareable*/ true);
    }

    public MockAction(
        Iterable<Artifact> inputs,
        ImmutableSet<Artifact> outputs,
        boolean middleman,
        boolean isShareable) {
      super(
          NULL_ACTION_OWNER,
          NestedSetBuilder.<Artifact>stableOrder().addAll(inputs).build(),
          outputs);
      this.middleman = middleman;
      this.isShareable = isShareable;
    }

    @Override
    public MiddlemanType getActionType() {
      // RUNFILES_MIDDLEMAN is chosen arbitrarily among the middleman types.
      return middleman ? MiddlemanType.RUNFILES_MIDDLEMAN : super.getActionType();
    }

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

    @Override
    protected void computeKey(
        ActionKeyContext actionKeyContext,
        @Nullable ArtifactExpander artifactExpander,
        Fingerprint fp) {
      fp.addString("Mock Action " + getPrimaryOutput());
    }

    @Override
    public ActionResult execute(ActionExecutionContext actionExecutionContext) {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean isShareable() {
      return isShareable;
    }
  }

  /**
   * For a bunch of actions, gets the basenames of the paths and accumulates them in a space
   * separated string, like <code>foo.o bar.o baz.a</code>.
   */
  public static String baseNamesOf(NestedSet<Artifact> artifacts) {
    return baseNamesOf(artifacts.toList());
  }

  /**
   * For a bunch of actions, gets the basenames of the paths and accumulates them in a space
   * separated string, like <code>foo.o bar.o baz.a</code>.
   */
  public static String baseNamesOf(Iterable<Artifact> artifacts) {
    List<String> baseNames = baseArtifactNames(artifacts);
    return Joiner.on(' ').join(baseNames);
  }

  /**
   * For a bunch of actions, gets the basenames of the paths, sorts them in alphabetical order and
   * accumulates them in a space separated string, for example <code>bar.o baz.a foo.o</code>.
   */
  public static String sortedBaseNamesOf(NestedSet<Artifact> artifacts) {
    return sortedBaseNamesOf(artifacts.toList());
  }

  /**
   * For a bunch of actions, gets the basenames of the paths, sorts them in alphabetical order and
   * accumulates them in a space separated string, for example <code>bar.o baz.a foo.o</code>.
   */
  public static String sortedBaseNamesOf(Iterable<Artifact> artifacts) {
    List<String> baseNames = baseArtifactNames(artifacts);
    Collections.sort(baseNames);
    return Joiner.on(' ').join(baseNames);
  }

  /** For a bunch of artifacts, gets the basenames and accumulates them in a List. */
  public static List<String> baseArtifactNames(NestedSet<Artifact> artifacts) {
    return transform(artifacts.toList(), artifact -> artifact.getExecPath().getBaseName());
  }

  /** For a bunch of artifacts, gets the basenames and accumulates them in a List. */
  public static List<String> baseArtifactNames(Iterable<Artifact> artifacts) {
    return transform(artifacts, artifact -> artifact.getExecPath().getBaseName());
  }

  /** For a bunch of artifacts, gets the exec paths and accumulates them in a List. */
  public static List<String> execPaths(NestedSet<Artifact> artifacts) {
    return execPaths(artifacts.toList());
  }

  /** For a bunch of artifacts, gets the exec paths and accumulates them in a List. */
  public static List<String> execPaths(Iterable<Artifact> artifacts) {
    return transform(artifacts, Artifact::getExecPathString);
  }

  /**
   * For a bunch of artifacts, gets the pretty printed names and accumulates them in a List. Note
   * that this returns the root-relative paths, not the exec paths.
   */
  public static List<String> prettyArtifactNames(NestedSet<Artifact> artifacts) {
    return prettyArtifactNames(artifacts.toList());
  }

  /**
   * For a bunch of artifacts, gets the pretty printed names and accumulates them in a List. Note
   * that this returns the root-relative paths, not the exec paths.
   */
  public static List<String> prettyArtifactNames(Iterable<Artifact> artifacts) {
    return transform(artifacts, Artifact::prettyPrint);
  }

  public static <T, R> List<R> transform(Iterable<T> iterable, Function<T, R> mapper) {
    // Can not use com.google.common.collect.Iterables.transform() there, as it returns Iterable.
    return stream(iterable).map(mapper).collect(Collectors.toList());
  }

  /**
   * Returns the closure of the predecessors of any of the given types, joining the basenames of the
   * artifacts into a space-separated string like "libfoo.a libbar.a libbaz.a".
   */
  public String predecessorClosureOf(Artifact artifact, FileType... types) {
    return predecessorClosureOf(Collections.singleton(artifact), types);
  }

  /**
   * Returns the closure of the predecessors of any of the given types, joining the basenames of the
   * artifacts into a space-separated string like "libfoo.a libbar.a libbaz.a".
   */
  public String predecessorClosureOf(NestedSet<Artifact> artifacts, FileType... types) {
    return predecessorClosureOf(artifacts.toList(), types);
  }

  /**
   * Returns the closure of the predecessors of any of the given types, joining the basenames of the
   * artifacts into a space-separated string like "libfoo.a libbar.a libbaz.a".
   */
  public String predecessorClosureOf(Iterable<Artifact> artifacts, FileType... types) {
    Set<Artifact> visited = artifactClosureOf(artifacts);
    return baseNamesOf(FileType.filter(visited, types));
  }

  /** Returns the closure of the predecessors of any of the given types. */
  public Collection<String> predecessorClosureAsCollection(Artifact artifact, FileType... types) {
    return predecessorClosureAsCollection(Collections.singleton(artifact), types);
  }

  /** Returns the closure of the predecessors of any of the given types. */
  public Collection<String> predecessorClosureAsCollection(
      NestedSet<Artifact> artifacts, FileType... types) {
    return predecessorClosureAsCollection(artifacts.toList(), types);
  }

  /** Returns the closure of the predecessors of any of the given types. */
  public Collection<String> predecessorClosureAsCollection(
      Iterable<Artifact> artifacts, FileType... types) {
    return baseArtifactNames(FileType.filter(artifactClosureOf(artifacts), types));
  }

  /** Returns the closure over the input files of an action. */
  public Set<Artifact> inputClosureOf(ActionAnalysisMetadata action) {
    return artifactClosureOf(action.getInputs().toList());
  }

  /** Returns the closure over the input files of an artifact. */
  public Set<Artifact> artifactClosureOf(Artifact artifact) {
    return artifactClosureOf(Collections.singleton(artifact));
  }

  /** Returns the closure over the input files of a set of artifacts. */
  public Set<Artifact> artifactClosureOf(NestedSet<Artifact> artifacts) {
    return artifactClosureOf(artifacts.toList());
  }

  /** Returns the closure over the input files of a set of artifacts. */
  public Set<Artifact> artifactClosureOf(Iterable<Artifact> artifacts) {
    Set<Artifact> visited = new LinkedHashSet<>();
    List<Artifact> toVisit = Lists.newArrayList(artifacts);
    while (!toVisit.isEmpty()) {
      Artifact current = toVisit.remove(0);
      if (!visited.add(current)) {
        continue;
      }
      ActionAnalysisMetadata generatingAction = actionGraph.getGeneratingAction(current);
      if (generatingAction != null) {
        toVisit.addAll(generatingAction.getInputs().toList());
      }
    }
    return visited;
  }

  /** Returns the closure over the input files of an artifact, filtered by the given matcher. */
  public ImmutableSet<Artifact> filteredArtifactClosureOf(
      Artifact artifact, Predicate<Artifact> matcher) {
    return artifactClosureOf(artifact).stream().filter(matcher).collect(toImmutableSet());
  }

  /** Returns a predicate to match {@link Artifact}s with the given root-relative path suffix. */
  public static Predicate<Artifact> getArtifactSuffixMatcher(String suffix) {
    return input -> input.getRootRelativePath().getPathString().endsWith(suffix);
  }

  /**
   * Finds all the actions that are instances of {@code actionClass} in the transitive closure of
   * prerequisites.
   */
  public <A extends Action> List<A> findTransitivePrerequisitesOf(
      Artifact artifact, Class<A> actionClass, Predicate<Artifact> allowedArtifacts) {
    List<A> actions = new ArrayList<>();
    Set<Artifact> visited = new HashSet<>();
    Queue<Artifact> toVisit = new ArrayDeque<>();
    toVisit.add(artifact);
    while (!toVisit.isEmpty()) {
      Artifact current = toVisit.remove();
      if (!visited.add(current)) {
        continue;
      }
      ActionAnalysisMetadata generatingAction = actionGraph.getGeneratingAction(current);
      if (generatingAction != null) {
        generatingAction.getInputs().toList().stream()
            .filter(allowedArtifacts)
            .forEach(toVisit::add);
        if (actionClass.isInstance(generatingAction)) {
          actions.add(actionClass.cast(generatingAction));
        }
      }
    }
    return actions;
  }

  public <A extends Action> List<A> findTransitivePrerequisitesOf(
      Artifact artifact, Class<A> actionClass) {
    return findTransitivePrerequisitesOf(artifact, actionClass, Predicates.alwaysTrue());
  }

  /**
   * Looks in the given artifacts Iterable for the first Artifact whose path ends with the given
   * suffix and returns its generating Action.
   */
  public Action getActionForArtifactEndingWith(NestedSet<Artifact> artifacts, String suffix) {
    return getActionForArtifactEndingWith(artifacts.toList(), suffix);
  }

  /**
   * Looks in the given artifacts Iterable for the first Artifact whose path ends with the given
   * suffix and returns its generating Action.
   */
  public Action getActionForArtifactEndingWith(Iterable<Artifact> artifacts, String suffix) {
    Artifact a = getFirstArtifactEndingWith(artifacts, suffix);

    if (a == null) {
      return null;
    }

    ActionAnalysisMetadata action = actionGraph.getGeneratingAction(a);
    if (action != null) {
      Preconditions.checkState(
          action instanceof Action, "%s is not a proper Action object", action.prettyPrint());
      return (Action) action;
    } else {
      return null;
    }
  }

  /** Returns the first artifact found in the given set whose path ends with the given suffix. */
  public static Artifact getFirstArtifactEndingWith(
      NestedSet<? extends Artifact> artifacts, String suffix) {
    return getFirstArtifactEndingWith(artifacts.toList(), suffix);
  }

  /**
   * Returns the first artifact found in the given Iterable whose path ends with the given suffix.
   */
  public static Artifact getFirstArtifactEndingWith(
      Iterable<? extends Artifact> artifacts, String suffix) {
    return getFirstArtifactMatching(
        artifacts, artifact -> artifact.getExecPath().getPathString().endsWith(suffix));
  }

  public static Artifact getFirstDerivedArtifactEndingWith(
      NestedSet<? extends Artifact> artifacts, String suffix) {
    return getFirstArtifactMatching(
        artifacts.toList(),
        artifact ->
            artifact instanceof DerivedArtifact
                && artifact.getExecPath().getPathString().endsWith(suffix));
  }

  /** Returns the first Artifact in the provided Iterable that matches the specified predicate. */
  public static Artifact getFirstArtifactMatching(
      Iterable<? extends Artifact> artifacts, Predicate<Artifact> predicate) {
    for (Artifact a : artifacts) {
      if (predicate.test(a)) {
        return a;
      }
    }
    return null;
  }

  /**
   * Returns a list of the Artifacts in <code>artifacts</code> whose paths end with the given
   * suffix.
   */
  public static List<Artifact> getArtifactsEndingWith(
      Iterable<? extends Artifact> artifacts, String suffix) {
    List<Artifact> result = new ArrayList<>();
    for (Artifact a : artifacts) {
      if (a.getExecPath().getPathString().endsWith(suffix)) {
        result.add(a);
      }
    }
    return result;
  }

  /**
   * Returns the first artifact which is an input to "action" and has the specified basename. An
   * assertion error is raised if none is found.
   */
  public static Artifact getInput(ActionAnalysisMetadata action, String basename) {
    for (Artifact artifact : action.getInputs().toList()) {
      if (artifact.getExecPath().getBaseName().equals(basename)) {
        return artifact;
      }
    }
    throw new AssertionError("No input with basename '" + basename + "' in action " + action);
  }

  /** Returns true if an artifact that is an input to "action" with the specific basename exists. */
  public static boolean hasInput(ActionAnalysisMetadata action, String basename) {
    try {
      getInput(action, basename);
      return true;
    } catch (AssertionError e) {
      return false;
    }
  }

  /**
   * Returns the first artifact which is an output of "action" and has the specified basename. An
   * assertion error is raised if none is found.
   */
  public static Artifact getOutput(ActionAnalysisMetadata action, String basename) {
    for (Artifact artifact : action.getOutputs()) {
      if (artifact.getExecPath().getBaseName().equals(basename)) {
        return artifact;
      }
    }
    throw new AssertionError("No output with basename '" + basename + "' in action " + action);
  }

  public static SpawnActionTemplate createDummySpawnActionTemplate(
      SpecialArtifact inputTreeArtifact, SpecialArtifact outputTreeArtifact) {
    return new SpawnActionTemplate.Builder(inputTreeArtifact, outputTreeArtifact)
        .setCommandLineTemplate(CustomCommandLine.builder().build())
        .setExecutable(PathFragment.create("bin/executable"))
        .setOutputPathMapper(TreeFileArtifact::getParentRelativePath)
        .build(NULL_ACTION_OWNER);
  }

  /** Builder for a list of {@link MissDetail}s with defaults set to zero for all possible items. */
  public static class MissDetailsBuilder {
    private final Map<MissReason, Integer> details = new EnumMap<>(MissReason.class);

    /** Constructs a new builder with all possible cache miss reasons set to zero counts. */
    public MissDetailsBuilder() {
      for (MissReason reason : MissReason.values()) {
        if (reason == MissReason.UNRECOGNIZED) {
          // The presence of this enum value is a protobuf artifact and not part of our metrics
          // collection. Just skip it.
          continue;
        }
        details.put(reason, 0);
      }
    }

    /** Sets the count of the given miss reason to the given value. */
    @CanIgnoreReturnValue
    public MissDetailsBuilder set(MissReason reason, int count) {
      checkArgument(details.containsKey(reason));
      details.put(reason, count);
      return this;
    }

    /** Constructs the list of {@link MissDetail}s. */
    public Iterable<MissDetail> build() {
      List<MissDetail> result = new ArrayList<>(details.size());
      for (Map.Entry<MissReason, Integer> entry : details.entrySet()) {
        MissDetail detail =
            MissDetail.newBuilder().setReason(entry.getKey()).setCount(entry.getValue()).build();
        result.add(detail);
      }
      return result;
    }
  }

  /**
   * An {@link ArtifactResolver} all of whose operations throw an exception.
   *
   * <p>This is to be used as a base class by other test programs that need to implement only a few
   * of the hooks required by the scenario under test.
   */
  public static class FakeArtifactResolverBase implements ArtifactResolver {
    @Override
    public SourceArtifact getSourceArtifact(PathFragment execPath, Root root, ArtifactOwner owner) {
      throw new UnsupportedOperationException();
    }

    @Override
    public SourceArtifact getSourceArtifact(PathFragment execPath, Root root) {
      throw new UnsupportedOperationException();
    }

    @Override
    public SourceArtifact resolveSourceArtifact(
        PathFragment execPath, RepositoryName repositoryName) {
      throw new UnsupportedOperationException();
    }

    @Override
    public Map<PathFragment, SourceArtifact> resolveSourceArtifacts(
        Iterable<PathFragment> execPaths, PackageRootResolver resolver) {
      throw new UnsupportedOperationException();
    }

    @Override
    public Path getPathFromSourceExecPath(Path execRoot, PathFragment execPath) {
      throw new UnsupportedOperationException();
    }
  }

  /**
   * A {@link MetadataHandler} for tests that throws {@link UnsupportedOperationException} for its
   * operations.
   */
  public static final MetadataHandler THROWING_METADATA_HANDLER =
      new FakeMetadataHandlerBase() {
        @Override
        public String toString() {
          return "THROWING_METADATA_HANDLER";
        }
      };

  /**
   * A {@link MetadataHandler} all of whose operations throw an exception.
   *
   * <p>This is to be used as a base class by other test programs that need to implement only a few
   * of the hooks required by the scenario under test. Tests that need an instance but do not need
   * any functionality can use {@link #THROWING_METADATA_HANDLER}.
   */
  public static class FakeMetadataHandlerBase implements MetadataHandler {
    @Override
    public FileArtifactValue getMetadata(ActionInput input) throws IOException {
      throw new UnsupportedOperationException();
    }

    @Override
    public ActionInput getInput(String execPath) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void setDigestForVirtualArtifact(Artifact artifact, byte[] digest) {
      throw new UnsupportedOperationException();
    }

    @Override
    public ImmutableSet<TreeFileArtifact> getTreeArtifactChildren(SpecialArtifact treeArtifact) {
      throw new UnsupportedOperationException();
    }

    @Override
    public TreeArtifactValue getTreeArtifactValue(SpecialArtifact treeArtifact) throws IOException {
      throw new UnsupportedOperationException();
    }

    @Override
    public FileArtifactValue constructMetadataForDigest(
        Artifact output, FileStatus statNoFollow, byte[] digest) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void injectFile(Artifact output, FileArtifactValue metadata) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void injectTree(SpecialArtifact treeArtifact, TreeArtifactValue tree) {
      throw new UnsupportedOperationException();
    }

    @Override
    public void markOmitted(Artifact output) {
      throw new UnsupportedOperationException();
    }

    @Override
    public boolean artifactOmitted(Artifact artifact) {
      return false;
    }

    @Override
    public void resetOutputs(Iterable<? extends Artifact> outputs) {
      throw new UnsupportedOperationException();
    }
  }
}
