// Copyright 2019 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.analysis.util;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.devtools.build.lib.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;
import static org.junit.Assert.fail;

import com.google.common.base.Ascii;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Predicate;
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.collect.Sets;
import com.google.common.eventbus.EventBus;
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.ActionKeyContext;
import com.google.devtools.build.lib.actions.ActionLogBufferPathGenerator;
import com.google.devtools.build.lib.actions.ActionLookupValue;
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.SpecialArtifact;
import com.google.devtools.build.lib.actions.ArtifactOwner;
import com.google.devtools.build.lib.actions.ArtifactPathResolver;
import com.google.devtools.build.lib.actions.ArtifactRoot;
import com.google.devtools.build.lib.actions.CommandAction;
import com.google.devtools.build.lib.actions.CommandLine;
import com.google.devtools.build.lib.actions.CommandLineExpansionException;
import com.google.devtools.build.lib.actions.CommandLines;
import com.google.devtools.build.lib.actions.CommandLines.CommandLineAndParamFileInfo;
import com.google.devtools.build.lib.actions.MapBasedActionGraph;
import com.google.devtools.build.lib.actions.MetadataProvider;
import com.google.devtools.build.lib.actions.MiddlemanFactory;
import com.google.devtools.build.lib.actions.MutableActionGraph;
import com.google.devtools.build.lib.actions.ParameterFile;
import com.google.devtools.build.lib.actions.util.ActionsTestUtil;
import com.google.devtools.build.lib.actions.util.DummyExecutor;
import com.google.devtools.build.lib.analysis.AnalysisEnvironment;
import com.google.devtools.build.lib.analysis.AnalysisOptions;
import com.google.devtools.build.lib.analysis.AnalysisResult;
import com.google.devtools.build.lib.analysis.AnalysisUtils;
import com.google.devtools.build.lib.analysis.BlazeDirectories;
import com.google.devtools.build.lib.analysis.CachingAnalysisEnvironment;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.ExtraActionArtifactsProvider;
import com.google.devtools.build.lib.analysis.FileProvider;
import com.google.devtools.build.lib.analysis.FilesToRunProvider;
import com.google.devtools.build.lib.analysis.OutputGroupInfo;
import com.google.devtools.build.lib.analysis.PseudoAction;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.Runfiles;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.RunfilesSupport;
import com.google.devtools.build.lib.analysis.ServerDirectories;
import com.google.devtools.build.lib.analysis.TransitiveInfoCollection;
import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
import com.google.devtools.build.lib.analysis.WorkspaceStatusAction;
import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
import com.google.devtools.build.lib.analysis.actions.SpawnAction;
import com.google.devtools.build.lib.analysis.buildinfo.BuildInfoFactory.BuildInfoKey;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.config.BuildConfigurationCollection;
import com.google.devtools.build.lib.analysis.config.BuildOptions;
import com.google.devtools.build.lib.analysis.config.CoreOptions.ConfigsMode;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.analysis.config.transitions.NoTransition;
import com.google.devtools.build.lib.analysis.config.transitions.NullTransition;
import com.google.devtools.build.lib.analysis.config.transitions.PatchTransition;
import com.google.devtools.build.lib.analysis.configuredtargets.FileConfiguredTarget;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget;
import com.google.devtools.build.lib.analysis.extra.ExtraAction;
import com.google.devtools.build.lib.analysis.skylark.StarlarkTransition;
import com.google.devtools.build.lib.analysis.test.BaselineCoverageAction;
import com.google.devtools.build.lib.analysis.test.InstrumentedFilesInfo;
import com.google.devtools.build.lib.buildtool.BuildRequestOptions;
import com.google.devtools.build.lib.clock.BlazeClock;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelConstants;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.cmdline.PackageIdentifier;
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.Event;
import com.google.devtools.build.lib.events.ExtendedEventHandler;
import com.google.devtools.build.lib.events.StoredEventHandler;
import com.google.devtools.build.lib.exec.ExecutionOptions;
import com.google.devtools.build.lib.packages.AspectClass;
import com.google.devtools.build.lib.packages.AspectDescriptor;
import com.google.devtools.build.lib.packages.AspectParameters;
import com.google.devtools.build.lib.packages.AttributeMap;
import com.google.devtools.build.lib.packages.ConfiguredAttributeMapper;
import com.google.devtools.build.lib.packages.ConstantRuleVisibility;
import com.google.devtools.build.lib.packages.ImplicitOutputsFunction.SafeImplicitOutputsFunction;
import com.google.devtools.build.lib.packages.NativeAspectClass;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.OutputFile;
import com.google.devtools.build.lib.packages.PackageFactory;
import com.google.devtools.build.lib.packages.PackageFactory.EnvironmentExtension;
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.StarlarkSemanticsOptions;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.util.MockToolsConfig;
import com.google.devtools.build.lib.pkgcache.LoadingOptions;
import com.google.devtools.build.lib.pkgcache.PackageCacheOptions;
import com.google.devtools.build.lib.pkgcache.PackageManager;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.rules.repository.ManagedDirectoriesKnowledge;
import com.google.devtools.build.lib.rules.repository.RepositoryDelegatorFunction;
import com.google.devtools.build.lib.skyframe.AspectValue;
import com.google.devtools.build.lib.skyframe.BazelSkyframeExecutorConstants;
import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.PackageRootsNoSymlinkCreation;
import com.google.devtools.build.lib.skyframe.PrecomputedValue;
import com.google.devtools.build.lib.skyframe.SequencedSkyframeExecutor;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.skyframe.TargetPatternPhaseValue;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.testutil.BlazeTestUtils;
import com.google.devtools.build.lib.testutil.FoundationTestCase;
import com.google.devtools.build.lib.testutil.TestConstants;
import com.google.devtools.build.lib.util.StringUtil;
import com.google.devtools.build.lib.util.io.TimestampGranularityMonitor;
import com.google.devtools.build.lib.vfs.ModifiedFileSet;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.build.lib.vfs.Root;
import com.google.devtools.build.lib.vfs.RootedPath;
import com.google.devtools.build.skyframe.ErrorInfo;
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.common.options.Options;
import com.google.devtools.common.options.OptionsParser;
import com.google.devtools.common.options.OptionsParsingException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import javax.annotation.Nullable;
import org.junit.Before;

/**
 * Common test code that creates a BuildView instance.
 */
public abstract class BuildViewTestCase extends FoundationTestCase {
  protected static final int LOADING_PHASE_THREADS = 20;

  protected AnalysisMock analysisMock;
  protected ConfiguredRuleClassProvider ruleClassProvider;
  protected BuildViewForTesting view;

  protected SequencedSkyframeExecutor skyframeExecutor;

  protected TimestampGranularityMonitor tsgm;
  protected BlazeDirectories directories;
  protected ActionKeyContext actionKeyContext;

  // Note that these configurations are virtual (they use only VFS)
  protected BuildConfigurationCollection masterConfig;
  protected BuildConfiguration targetConfig;  // "target" or "build" config
  private List<String> configurationArgs;
  private ConfigsMode configsMode = ConfigsMode.NOTRIM;

  protected OptionsParser optionsParser;
  private PackageCacheOptions packageCacheOptions;
  private StarlarkSemanticsOptions starlarkSemanticsOptions;
  protected PackageFactory pkgFactory;

  protected MockToolsConfig mockToolsConfig;

  protected WorkspaceStatusAction.Factory workspaceStatusActionFactory;

  private MutableActionGraph mutableActionGraph;

  private LoadingOptions customLoadingOptions = null;
  protected BuildConfigurationValue.Key targetConfigKey;

  private ActionLogBufferPathGenerator actionLogBufferPathGenerator;

  @Before
  public final void initializeSkyframeExecutor() throws Exception {
    initializeSkyframeExecutor(/*doPackageLoadingChecks=*/ true);
  }

  public void initializeSkyframeExecutor(boolean doPackageLoadingChecks) throws Exception {
    analysisMock = getAnalysisMock();
    directories =
        new BlazeDirectories(
            new ServerDirectories(outputBase, outputBase, outputBase),
            rootDirectory,
            /* defaultSystemJavabase= */ null,
            analysisMock.getProductName());

    actionKeyContext = new ActionKeyContext();
    mockToolsConfig = new MockToolsConfig(rootDirectory, false);
    mockToolsConfig.create("/bazel_tools_workspace/WORKSPACE", "workspace(name = 'bazel_tools')");
    mockToolsConfig.create("/bazel_tools_workspace/tools/build_defs/repo/BUILD");
    mockToolsConfig.create(
        "/bazel_tools_workspace/tools/build_defs/repo/utils.bzl",
        "def maybe(repo_rule, name, **kwargs):",
        "  if name not in native.existing_rules():",
        "    repo_rule(name = name, **kwargs)");
    mockToolsConfig.create(
        "/bazel_tools_workspace/tools/build_defs/repo/http.bzl",
        "def http_archive(**kwargs):",
        "  pass",
        "",
        "def http_file(**kwargs):",
        "  pass");
    initializeMockClient();

    packageCacheOptions = parsePackageCacheOptions();
    starlarkSemanticsOptions = parseSkylarkSemanticsOptions();
    workspaceStatusActionFactory = new AnalysisTestUtil.DummyWorkspaceStatusActionFactory();
    mutableActionGraph = new MapBasedActionGraph(actionKeyContext);
    ruleClassProvider = getRuleClassProvider();
    getOutputPath().createDirectoryAndParents();
    ImmutableList<PrecomputedValue.Injected> extraPrecomputedValues =
        ImmutableList.of(
            PrecomputedValue.injected(
                PrecomputedValue.STARLARK_SEMANTICS, StarlarkSemantics.DEFAULT_SEMANTICS),
            PrecomputedValue.injected(PrecomputedValue.REPO_ENV, ImmutableMap.<String, String>of()),
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.REPOSITORY_OVERRIDES,
                ImmutableMap.<RepositoryName, PathFragment>of()),
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.RESOLVED_FILE_INSTEAD_OF_WORKSPACE,
                Optional.<RootedPath>absent()),
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.DEPENDENCY_FOR_UNCONDITIONAL_FETCHING,
                RepositoryDelegatorFunction.DONT_FETCH_UNCONDITIONALLY),
            PrecomputedValue.injected(
                PrecomputedValue.BUILD_INFO_FACTORIES,
                ruleClassProvider.getBuildInfoFactoriesAsMap()));
    PackageFactory.BuilderForTesting pkgFactoryBuilder =
        analysisMock
            .getPackageFactoryBuilderForTesting(directories)
            .setExtraPrecomputeValues(extraPrecomputedValues)
            .setEnvironmentExtensions(getEnvironmentExtensions());
    if (!doPackageLoadingChecks) {
      pkgFactoryBuilder.disableChecks();
    }
    pkgFactory = pkgFactoryBuilder.build(ruleClassProvider, fileSystem);
    tsgm = new TimestampGranularityMonitor(BlazeClock.instance());
    skyframeExecutor =
        BazelSkyframeExecutorConstants.newBazelSkyframeExecutorBuilder()
            .setPkgFactory(pkgFactory)
            .setFileSystem(fileSystem)
            .setDirectories(directories)
            .setActionKeyContext(actionKeyContext)
            .setDefaultBuildOptions(
                DefaultBuildOptionsForTesting.getDefaultBuildOptionsForTest(ruleClassProvider))
            .setWorkspaceStatusActionFactory(workspaceStatusActionFactory)
            .setExtraSkyFunctions(analysisMock.getSkyFunctions(directories))
            .setManagedDirectoriesKnowledge(getManagedDirectoriesKnowledge())
            .build();
    TestConstants.processSkyframeExecutorForTesting(skyframeExecutor);
    skyframeExecutor.injectExtraPrecomputedValues(extraPrecomputedValues);
    packageCacheOptions.defaultVisibility = ConstantRuleVisibility.PUBLIC;
    packageCacheOptions.showLoadingProgress = true;
    packageCacheOptions.globbingThreads = 7;
    skyframeExecutor.preparePackageLoading(
        new PathPackageLocator(
            outputBase,
            ImmutableList.of(root),
            BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY),
        packageCacheOptions,
        starlarkSemanticsOptions,
        UUID.randomUUID(),
        ImmutableMap.<String, String>of(),
        tsgm);
    skyframeExecutor.setActionEnv(ImmutableMap.<String, String>of());
    useConfiguration();
    setUpSkyframe();
    this.actionLogBufferPathGenerator =
        new ActionLogBufferPathGenerator(
            directories.getActionTempsDirectory(getExecRoot()),
            directories.getPersistentActionOutsDirectory(getExecRoot()));
  }

  public void initializeMockClient() throws IOException {
    analysisMock.setupMockClient(mockToolsConfig);
    analysisMock.setupMockWorkspaceFiles(directories.getEmbeddedBinariesRoot());
  }

  protected AnalysisMock getAnalysisMock() {
    return AnalysisMock.get();
  }

  /** Creates or retrieves the rule class provider used in this test. */
  protected ConfiguredRuleClassProvider getRuleClassProvider() {
    return getAnalysisMock().createRuleClassProvider();
  }

  protected ManagedDirectoriesKnowledge getManagedDirectoriesKnowledge() {
    return null;
  }

  protected PackageFactory getPackageFactory() {
    return pkgFactory;
  }

  protected Iterable<EnvironmentExtension> getEnvironmentExtensions() {
    return ImmutableList.<EnvironmentExtension>of();
  }

  protected StarlarkSemantics getSkylarkSemantics() {
    return starlarkSemanticsOptions.toSkylarkSemantics();
  }

  protected final BuildConfigurationCollection createConfigurations(
      ImmutableMap<String, Object> skylarkOptions, String... args) throws Exception {
    optionsParser =
        OptionsParser.builder()
            .optionsClasses(
                Iterables.concat(
                    Arrays.asList(ExecutionOptions.class, BuildRequestOptions.class),
                    ruleClassProvider.getConfigurationOptions()))
            .build();
    List<String> allArgs = new ArrayList<>();
    // TODO(dmarting): Add --stamp option only to test that requires it.
    allArgs.add("--stamp");  // Stamp is now defaulted to false.
    allArgs.add("--experimental_extended_sanity_checks");
    allArgs.add("--features=cc_include_scanning");
    // Always default to k8, even on mac and windows. Tests that need different cpu should set it
    // using {@link useConfiguration()} explicitly.
    allArgs.add("--cpu=k8");
    allArgs.add("--host_cpu=k8");

    optionsParser.parse(allArgs);
    optionsParser.parse(args);

    // TODO(juliexxia): when the starlark options parsing work goes in, add type verification here.
    optionsParser.setStarlarkOptions(skylarkOptions);

    BuildOptions buildOptions = ruleClassProvider.createBuildOptions(optionsParser);
    return skyframeExecutor.createConfigurations(
        reporter, buildOptions, ImmutableSet.<String>of(), false);
  }

  protected Target getTarget(String label)
      throws NoSuchPackageException, NoSuchTargetException,
      LabelSyntaxException, InterruptedException {
    return getTarget(Label.parseAbsolute(label, ImmutableMap.of()));
  }

  protected Target getTarget(Label label)
      throws NoSuchPackageException, NoSuchTargetException, InterruptedException {
    return getPackageManager().getTarget(reporter, label);
  }

  /**
   * Checks that loading the given target fails with the expected error message.
   *
   * <p>Fails with an assertion error if this doesn't happen.
   *
   * <p>This method is useful for checking loading phase errors. Analysis phase errors can be
   * checked with {@link #getConfiguredTarget} and related methods.
   */
  protected void assertTargetError(String label, String expectedError)
      throws InterruptedException {
    try {
      getTarget(label);
      fail("Expected loading phase failure for target " + label);
    } catch (NoSuchPackageException | NoSuchTargetException | LabelSyntaxException e) {
      // Target loading failed as expected.
    }
    assertContainsEvent(expectedError);
  }

  private void setUpSkyframe() {
    PathPackageLocator pkgLocator =
        PathPackageLocator.create(
            outputBase,
            packageCacheOptions.packagePath,
            reporter,
            rootDirectory,
            rootDirectory,
            BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY);
    packageCacheOptions.showLoadingProgress = true;
    packageCacheOptions.globbingThreads = 7;
    skyframeExecutor.preparePackageLoading(
        pkgLocator,
        packageCacheOptions,
        starlarkSemanticsOptions,
        UUID.randomUUID(),
        ImmutableMap.<String, String>of(),
        tsgm);
    skyframeExecutor.setActionEnv(ImmutableMap.<String, String>of());
    skyframeExecutor.setDeletedPackages(ImmutableSet.copyOf(packageCacheOptions.getDeletedPackages()));
    skyframeExecutor.injectExtraPrecomputedValues(
        ImmutableList.of(
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.RESOLVED_FILE_INSTEAD_OF_WORKSPACE,
                Optional.<RootedPath>absent()),
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.OUTPUT_VERIFICATION_REPOSITORY_RULES,
                ImmutableSet.<String>of()),
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.RESOLVED_FILE_FOR_VERIFICATION,
                Optional.<RootedPath>absent())));
  }

  protected void setPackageCacheOptions(String... options) throws Exception {
    packageCacheOptions = parsePackageCacheOptions(options);
    setUpSkyframe();
  }

  protected void setSkylarkSemanticsOptions(String... options) throws Exception {
    starlarkSemanticsOptions = parseSkylarkSemanticsOptions(options);
    setUpSkyframe();
  }

  private static PackageCacheOptions parsePackageCacheOptions(String... options) throws Exception {
    OptionsParser parser =
        OptionsParser.builder().optionsClasses(PackageCacheOptions.class).build();
    parser.parse("--default_visibility=public");
    parser.parse(options);
    return parser.getOptions(PackageCacheOptions.class);
  }

  private static StarlarkSemanticsOptions parseSkylarkSemanticsOptions(String... options)
      throws Exception {
    OptionsParser parser =
        OptionsParser.builder().optionsClasses(StarlarkSemanticsOptions.class).build();
    parser.parse(options);
    return parser.getOptions(StarlarkSemanticsOptions.class);
  }

  /** Used by skyframe-only tests. */
  protected SequencedSkyframeExecutor getSkyframeExecutor() {
    return Preconditions.checkNotNull(skyframeExecutor);
  }

  protected PackageManager getPackageManager() {
    return skyframeExecutor.getPackageManager();
  }

  protected void invalidatePackages() throws InterruptedException {
    invalidatePackages(true);
  }

  /**
   * Invalidates all existing packages. Optionally invalidates configurations too.
   *
   * <p>Tests should invalidate both unless they have specific reason not to.
   *
   * @throws InterruptedException
   */
  protected void invalidatePackages(boolean alsoConfigs) throws InterruptedException {
    skyframeExecutor.invalidateFilesUnderPathForTesting(
        reporter, ModifiedFileSet.EVERYTHING_MODIFIED, Root.fromPath(rootDirectory));
    if (alsoConfigs) {
      try {
        // Also invalidate all configurations. This is important: by invalidating all files we
        // invalidate CROSSTOOL, which invalidates CppConfiguration (and a few other fragments). So
        // we need to invalidate the {@link SkyframeBuildView#hostConfigurationCache} as well.
        // Otherwise we end up with old CppConfiguration instances. Even though they're logically
        // equal to the new ones, CppConfiguration has no .equals() method and some production code
        // expects equality.
        useConfiguration(configurationArgs.toArray(new String[0]));
      } catch (Exception e) {
        // There are enough dependers on this method that don't handle Exception that just passing
        // through the Exception would result in a huge refactoring. As it stands this shouldn't
        // fail anyway because this method only gets called after a successful useConfiguration()
        // call anyway.
        throw new RuntimeException(e);
      }
    }
  }

  /**
   * Sets host and target configuration using the specified options, falling back to the default
   * options for unspecified ones, and recreates the build view.
   *
   * TODO(juliexxia): when skylark option parsing exists, find a way to combine these parameters
   * into a single parameter so skylark/native options don't have to be specified separately.
   *
   * @param skylarkOptions map of skylark-defined options where the keys are option names (in the
   *     form of label-like strings) and the values are option values
   * @param args native option name/pair descriptions in command line form (e.g. "--cpu=k8")
   *
   * @throws IllegalArgumentException
   */
  protected void useConfiguration(ImmutableMap<String, Object> skylarkOptions, String... args)
      throws Exception {
    ImmutableList<String> actualArgs =
        ImmutableList.<String>builder()
            .addAll(TestConstants.PRODUCT_SPECIFIC_FLAGS)
            .add(args)
            .add("--experimental_dynamic_configs=" + Ascii.toLowerCase(configsMode.toString()))
            .build();

    masterConfig = createConfigurations(skylarkOptions, actualArgs.toArray(new String[0]));
    targetConfig = getTargetConfiguration();
    targetConfigKey = BuildConfigurationValue.key(targetConfig);
    configurationArgs = actualArgs;
    createBuildView();
  }

  protected void useConfiguration(String... args) throws Exception {
    useConfiguration(ImmutableMap.of(), args);
  }

  /**
   * Makes subsequent {@link #useConfiguration} calls automatically use the specified style for
   * configurations.
   */
  protected final void useConfigurationMode(ConfigsMode mode) {
    configsMode = mode;
  }

  /**
   * Creates BuildView using current hostConfig/targetConfig values.
   * Ensures that hostConfig is either identical to the targetConfig or has
   * 'host' short name.
   */
  protected final void createBuildView() throws Exception {
    Preconditions.checkNotNull(masterConfig);
    Preconditions.checkState(getHostConfiguration().equals(getTargetConfiguration())
        || getHostConfiguration().isHostConfiguration(),
        "Host configuration %s is not a host configuration' "
        + "and does not match target configuration %s",
        getHostConfiguration(), getTargetConfiguration());

    skyframeExecutor.handleAnalysisInvalidatingChange();

    view = new BuildViewForTesting(directories, ruleClassProvider, skyframeExecutor, null);
    view.setConfigurationsForTesting(event -> {}, masterConfig);

    view.setArtifactRoots(new PackageRootsNoSymlinkCreation(Root.fromPath(rootDirectory)));
  }

  protected CachingAnalysisEnvironment getTestAnalysisEnvironment() {
    return new CachingAnalysisEnvironment(
        view.getArtifactFactory(),
        actionKeyContext,
        new ActionLookupValue.ActionLookupKey() {
          @Override
          public SkyFunctionName functionName() {
            return null;
          }
        },
        /*isSystemEnv=*/ true,
        /*extendedSanityChecks=*/ false,
        /*allowAnalysisFailures=*/ false,
        reporter,
        skyframeExecutor.getSkyFunctionEnvironmentForTesting(reporter));
  }

  /**
   * Allows access to the prerequisites of a configured target. This is currently used in some tests
   * to reach into the internals of RuleCT for white box testing. In principle, this should not be
   * used; instead tests should only assert on properties of the exposed provider instances and / or
   * the action graph.
   */
  protected final Collection<ConfiguredTarget> getDirectPrerequisites(ConfiguredTarget target)
      throws Exception {
    return view.getDirectPrerequisitesForTesting(reporter, target, masterConfig);
  }

  protected final Collection<ConfiguredTargetAndData> getDirectPrerequisites(
      ConfiguredTargetAndData ctad) throws Exception {
    return view.getConfiguredTargetAndDataDirectPrerequisitesForTesting(
        reporter, ctad, masterConfig);
  }

  protected final ConfiguredTarget getDirectPrerequisite(ConfiguredTarget target, String label)
      throws Exception {
    Label candidateLabel = Label.parseAbsolute(label, ImmutableMap.of());
    for (ConfiguredTarget candidate : getDirectPrerequisites(target)) {
      if (candidate.getLabel().equals(candidateLabel)) {
        return candidate;
      }
    }

    return null;
  }

  protected final ConfiguredTargetAndData getConfiguredTargetAndDataDirectPrerequisite(
      ConfiguredTargetAndData ctad, String label) throws Exception {
    Label candidateLabel = Label.parseAbsolute(label, ImmutableMap.of());
    for (ConfiguredTargetAndData candidate : getDirectPrerequisites(ctad)) {
      if (candidate.getConfiguredTarget().getLabel().equals(candidateLabel)) {
        return candidate;
      }
    }
    return null;
  }

  /**
   * Asserts that two configurations are the same.
   *
   * <p>Historically this meant they contained the same object reference. But with upcoming dynamic
   * configurations that may no longer be true (for example, they may have the same values but not
   * the same {@link BuildConfiguration.Fragment}s. So this method abstracts the
   * "configuration equivalency" checking into one place, where the implementation logic can evolve
   * as needed.
   */
  protected void assertConfigurationsEqual(BuildConfiguration config1, BuildConfiguration config2) {
    // BuildOptions and crosstool files determine a configuration's content. Within the context
    // of these tests only the former actually change.
    assertThat(config2.cloneOptions()).isEqualTo(config1.cloneOptions());
  }

  /**
   * Creates and returns a rule context that is equivalent to the one that was used to create the
   * given configured target.
   */
  protected RuleContext getRuleContext(ConfiguredTarget target) throws Exception {
    return view.getRuleContextForTesting(
        reporter, target, new StubAnalysisEnvironment(), masterConfig);
  }

  protected RuleContext getRuleContext(ConfiguredTarget target,
      AnalysisEnvironment analysisEnvironment) throws Exception {
    return view.getRuleContextForTesting(
        reporter, target, analysisEnvironment, masterConfig);
  }

  /**
   * Creates and returns a rule context to use for Skylark tests that is equivalent to the one
   * that was used to create the given configured target.
   */
  protected RuleContext getRuleContextForSkylark(ConfiguredTarget target)
      throws Exception {
    // TODO(bazel-team): we need this horrible workaround because CachingAnalysisEnvironment
    // only works with StoredErrorEventListener despite the fact it accepts the interface
    // ErrorEventListener, so it's not possible to create it with reporter.
    // See BuildView.getRuleContextForTesting().
    StoredEventHandler eventHandler = new StoredEventHandler() {
      @Override
      public synchronized void handle(Event e) {
        super.handle(e);
        reporter.handle(e);
      }
    };
    return view.getRuleContextForTesting(target, eventHandler, masterConfig);
  }

  /**
   * Allows access to the prerequisites of a configured target. This is currently used in some tests
   * to reach into the internals of RuleCT for white box testing. In principle, this should not be
   * used; instead tests should only assert on properties of the exposed provider instances and / or
   * the action graph.
   */
  protected List<? extends TransitiveInfoCollection> getPrerequisites(ConfiguredTarget target,
      String attributeName) throws Exception {
    return getRuleContext(target).getConfiguredTargetMap().get(attributeName);
  }

  /**
   * Allows access to the prerequisites of a configured target. This is currently used in some tests
   * to reach into the internals of RuleCT for white box testing. In principle, this should not be
   * used; instead tests should only assert on properties of the exposed provider instances and / or
   * the action graph.
   */
  protected <C extends TransitiveInfoProvider> Iterable<C> getPrerequisites(ConfiguredTarget target,
      String attributeName, Class<C> classType) throws Exception {
    return AnalysisUtils.getProviders(getPrerequisites(target, attributeName), classType);
  }

  /**
   * Allows access to the prerequisites of a configured target. This is currently used in some tests
   * to reach into the internals of RuleCT for white box testing. In principle, this should not be
   * used; instead tests should only assert on properties of the exposed provider instances and / or
   * the action graph.
   */
  protected ImmutableList<Artifact> getPrerequisiteArtifacts(
      ConfiguredTarget target, String attributeName) throws Exception {
    Set<Artifact> result = new LinkedHashSet<>();
    for (FileProvider provider : getPrerequisites(target, attributeName, FileProvider.class)) {
      result.addAll(provider.getFilesToBuild().toList());
    }
    return ImmutableList.copyOf(result);
  }

  protected ActionGraph getActionGraph() {
    return skyframeExecutor.getActionGraph(reporter);
  }

  /** Locates the first parameter file used by the action and returns its command line. */
  @Nullable
  protected final CommandLine paramFileCommandLineForAction(Action action) {
    if (action instanceof SpawnAction) {
      CommandLines commandLines = ((SpawnAction) action).getCommandLines();
      for (CommandLineAndParamFileInfo pair : commandLines.getCommandLines()) {
        if (pair.paramFileInfo != null) {
          return pair.commandLine;
        }
      }
    }
    ParameterFileWriteAction parameterFileWriteAction = paramFileWriteActionForAction(action);
    return parameterFileWriteAction != null ? parameterFileWriteAction.getCommandLine() : null;
  }

  /** Locates the first parameter file used by the action and returns its args. */
  @Nullable
  protected final Iterable<String> paramFileArgsForAction(Action action)
      throws CommandLineExpansionException {
    CommandLine commandLine = paramFileCommandLineForAction(action);
    return commandLine != null ? commandLine.arguments() : null;
  }

  /**
   * Locates the first parameter file used by the action and returns its args.
   *
   * <p>If no param file is used, return the action's arguments.
   */
  @Nullable
  protected final Iterable<String> paramFileArgsOrActionArgs(CommandAction action)
      throws CommandLineExpansionException {
    CommandLine commandLine = paramFileCommandLineForAction(action);
    return commandLine != null ? commandLine.arguments() : action.getArguments();
  }

  /** Locates the first parameter file used by the action and returns its contents. */
  @Nullable
  protected final String paramFileStringContentsForAction(Action action)
      throws CommandLineExpansionException, IOException {
    if (action instanceof SpawnAction) {
      CommandLines commandLines = ((SpawnAction) action).getCommandLines();
      for (CommandLineAndParamFileInfo pair : commandLines.getCommandLines()) {
        if (pair.paramFileInfo != null) {
          ByteArrayOutputStream out = new ByteArrayOutputStream();
          ParameterFile.writeParameterFile(
              out,
              pair.commandLine.arguments(),
              pair.paramFileInfo.getFileType(),
              pair.paramFileInfo.getCharset());
          return new String(out.toByteArray(), pair.paramFileInfo.getCharset());
        }
      }
    }
    ParameterFileWriteAction parameterFileWriteAction = paramFileWriteActionForAction(action);
    return parameterFileWriteAction != null ? parameterFileWriteAction.getStringContents() : null;
  }

  @Nullable
  private ParameterFileWriteAction paramFileWriteActionForAction(Action action) {
    for (Artifact input : action.getInputs().toList()) {
      if (!(input instanceof SpecialArtifact)) {
        Action generatingAction = getGeneratingAction(input);
        if (generatingAction instanceof ParameterFileWriteAction) {
          return (ParameterFileWriteAction) generatingAction;
        }
      }
    }
    return null;
  }

  protected final ActionAnalysisMetadata getGeneratingActionAnalysisMetadata(Artifact artifact) {
    Preconditions.checkNotNull(artifact);
    ActionAnalysisMetadata actionAnalysisMetadata =
        mutableActionGraph.getGeneratingAction(artifact);

    if (actionAnalysisMetadata == null) {
      if (artifact.isSourceArtifact() || !((DerivedArtifact) artifact).hasGeneratingActionKey()) {
        return null;
      }
      actionAnalysisMetadata = getActionGraph().getGeneratingAction(artifact);
    }

    return actionAnalysisMetadata;
  }

  protected Action getGeneratingAction(ConfiguredTarget target, String outputName) {
    NestedSet<Artifact> filesToBuild = getFilesToBuild(target);
    return getGeneratingAction(outputName, filesToBuild, "filesToBuild");
  }

  private Action getGeneratingAction(
      String outputName, NestedSet<Artifact> filesToBuild, String providerName) {
    Artifact artifact = Iterables.find(filesToBuild.toList(), artifactNamed(outputName), null);
    if (artifact == null) {
      fail(
          String.format(
              "Artifact named '%s' not found in %s (%s)", outputName, providerName, filesToBuild));
    }
    return getGeneratingAction(artifact);
  }

  protected final Action getGeneratingAction(Artifact artifact) {
    ActionAnalysisMetadata action = getGeneratingActionAnalysisMetadata(artifact);

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

  protected Action getGeneratingActionInOutputGroup(
      ConfiguredTarget target, String outputName, String outputGroupName) {
    NestedSet<Artifact> outputGroup =
        OutputGroupInfo.get(target).getOutputGroup(outputGroupName);
    return getGeneratingAction(outputName, outputGroup, "outputGroup/" + outputGroupName);
  }

  /**
   * Returns the SpawnAction that generates an artifact.
   * Implicitly assumes the action is a SpawnAction.
   */
  protected final SpawnAction getGeneratingSpawnAction(Artifact artifact) {
    return (SpawnAction) getGeneratingAction(artifact);
  }

  protected SpawnAction getGeneratingSpawnAction(ConfiguredTarget target, String outputName) {
    return getGeneratingSpawnAction(
        Iterables.find(getFilesToBuild(target).toList(), artifactNamed(outputName)));
  }

  protected final List<String> getGeneratingSpawnActionArgs(Artifact artifact)
      throws CommandLineExpansionException {
    SpawnAction a = getGeneratingSpawnAction(artifact);
    return a.getArguments();
  }

  protected ActionsTestUtil actionsTestUtil() {
    return new ActionsTestUtil(getActionGraph());
  }

  // Get a MutableActionGraph for testing purposes.
  protected MutableActionGraph getMutableActionGraph() {
    return mutableActionGraph;
  }

  /**
   * Returns the ConfiguredTarget for the specified label, configured for the "build" (aka "target")
   * configuration. If the label corresponds to a target with a top-level configuration transition,
   * that transition is applied to the given config in the returned ConfiguredTarget.
   */
  public ConfiguredTarget getConfiguredTarget(String label) throws LabelSyntaxException {
    return getConfiguredTarget(label, targetConfig);
  }

  /**
   * Returns the ConfiguredTarget for the specified label, using the given build configuration. If
   * the label corresponds to a target with a top-level configuration transition, that transition is
   * applied to the given config in the returned ConfiguredTarget.
   */
  protected ConfiguredTarget getConfiguredTarget(String label, BuildConfiguration config)
      throws LabelSyntaxException {
    return getConfiguredTarget(Label.parseAbsolute(label, ImmutableMap.of()), config);
  }

  /**
   * Returns the ConfiguredTarget for the specified label, using the given build configuration. If
   * the label corresponds to a target with a top-level configuration transition, that transition is
   * applied to the given config in the returned ConfiguredTarget.
   *
   * <p>If the evaluation of the SkyKey corresponding to the configured target fails, this method
   * may return null. In that case, use a debugger to inspect the {@link ErrorInfo} for the
   * evaluation, which is produced by the {@link MemoizingEvaluator#getExistingValue} call in {@link
   * SkyframeExecutor#getConfiguredTargetForTesting}. See also b/26382502.
   *
   * @throws AssertionError if the target cannot be transitioned into with the given configuration
   */
  protected ConfiguredTarget getConfiguredTarget(Label label, BuildConfiguration config) {
    try {
      return view.getConfiguredTargetForTesting(
          reporter, BlazeTestUtils.convertLabel(label), config);
    } catch (InvalidConfigurationException | StarlarkTransition.TransitionException e) {
      throw new AssertionError(e);
    }
  }

  /**
   * Returns a ConfiguredTargetAndData for the specified label, using the given build configuration.
   */
  protected ConfiguredTargetAndData getConfiguredTargetAndData(
      Label label, BuildConfiguration config)
      throws StarlarkTransition.TransitionException, InvalidConfigurationException {
    return view.getConfiguredTargetAndDataForTesting(reporter, label, config);
  }

  /**
   * Returns the ConfiguredTargetAndData for the specified label. If the label corresponds to a
   * target with a top-level configuration transition, that transition is applied to the given
   * config in the ConfiguredTargetAndData's ConfiguredTarget.
   */
  public ConfiguredTargetAndData getConfiguredTargetAndData(String label)
      throws LabelSyntaxException, StarlarkTransition.TransitionException,
          InvalidConfigurationException {
    return getConfiguredTargetAndData(Label.parseAbsolute(label, ImmutableMap.of()), targetConfig);
  }

  /**
   * Returns the ConfiguredTarget for the specified file label, configured for the "build" (aka
   * "target") configuration.
   */
  protected FileConfiguredTarget getFileConfiguredTarget(String label) throws LabelSyntaxException {
    return (FileConfiguredTarget) getConfiguredTarget(label, targetConfig);
  }

  /**
   * Returns the ConfiguredTarget for the specified label, configured for the "host" configuration.
   */
  protected ConfiguredTarget getHostConfiguredTarget(String label) throws LabelSyntaxException {
    return getConfiguredTarget(label, getHostConfiguration());
  }

  /**
   * Returns the ConfiguredTarget for the specified file label, configured for the "host"
   * configuration.
   */
  protected FileConfiguredTarget getHostFileConfiguredTarget(String label)
      throws LabelSyntaxException {
    return (FileConfiguredTarget) getHostConfiguredTarget(label);
  }

  /**
   * Rewrites the WORKSPACE to have the required boilerplate and the given lines of content.
   *
   * <p>Triggers Skyframe to reinitialize everything.
   */
  public void rewriteWorkspace(String... lines) throws Exception {
    scratch.overwriteFile(
        "WORKSPACE",
        new ImmutableList.Builder<String>()
            .addAll(analysisMock.getWorkspaceContents(mockToolsConfig))
            .addAll(ImmutableList.copyOf(lines))
            .build());

    invalidatePackages();
  }

  /**
   * Create and return a configured scratch rule.
   *
   * @param packageName the package name of the rule.
   * @param ruleName the name of the rule.
   * @param lines the text of the rule.
   * @return the configured target instance for the created rule.
   * @throws IOException
   * @throws Exception
   */
  protected ConfiguredTarget scratchConfiguredTarget(
      String packageName, String ruleName, String... lines) throws IOException, Exception {
    return scratchConfiguredTarget(packageName, ruleName, targetConfig, lines);
  }

  /**
   * Create and return a configured scratch rule.
   *
   * @param packageName the package name of the rule.
   * @param ruleName the name of the rule.
   * @param config the configuration to use to construct the configured rule.
   * @param lines the text of the rule.
   * @return the configured target instance for the created rule.
   * @throws IOException
   * @throws Exception
   */
  protected ConfiguredTarget scratchConfiguredTarget(
      String packageName, String ruleName, BuildConfiguration config, String... lines)
      throws IOException, Exception {
    ConfiguredTargetAndData ctad =
        scratchConfiguredTargetAndData(packageName, ruleName, config, lines);
    return ctad == null ? null : ctad.getConfiguredTarget();
  }

  /**
   * Creates and returns a configured scratch rule and its data.
   *
   * @param packageName the package name of the rule.
   * @param rulename the name of the rule.
   * @param lines the text of the rule.
   * @return the configured tatarget and target instance for the created rule.
   * @throws Exception
   */
  protected ConfiguredTargetAndData scratchConfiguredTargetAndData(
      String packageName, String rulename, String... lines) throws Exception {
    return scratchConfiguredTargetAndData(packageName, rulename, targetConfig, lines);
  }

  /**
   * Creates and returns a configured scratch rule and its data.
   *
   * @param packageName the package name of the rule.
   * @param ruleName the name of the rule.
   * @param config the configuration to use to construct the configured rule.
   * @param lines the text of the rule.
   * @return the ConfiguredTargetAndData instance for the created rule.
   * @throws IOException
   * @throws Exception
   */
  protected ConfiguredTargetAndData scratchConfiguredTargetAndData(
      String packageName, String ruleName, BuildConfiguration config, String... lines)
      throws Exception {
    Target rule = scratchRule(packageName, ruleName, lines);
    return view.getConfiguredTargetAndDataForTesting(reporter, rule.getLabel(), config);
  }

  /**
   * Create and return a scratch rule.
   *
   * @param packageName the package name of the rule.
   * @param ruleName the name of the rule.
   * @param lines the text of the rule.
   * @return the rule instance for the created rule.
   * @throws IOException
   * @throws Exception
   */
  protected Rule scratchRule(String packageName, String ruleName, String... lines)
      throws Exception {
    // Allow to create the BUILD file also in the top package.
    String buildFilePathString = packageName.isEmpty() ? "BUILD" : packageName + "/BUILD";
    if (packageName.equals(LabelConstants.EXTERNAL_PACKAGE_NAME.getPathString())) {
      buildFilePathString = "WORKSPACE";
      scratch.overwriteFile(buildFilePathString, lines);
    } else {
      scratch.file(buildFilePathString, lines);
    }
    skyframeExecutor.invalidateFilesUnderPathForTesting(
        reporter,
        new ModifiedFileSet.Builder().modify(PathFragment.create(buildFilePathString)).build(),
        Root.fromPath(rootDirectory));
    return (Rule) getTarget("//" + packageName + ":" + ruleName);
  }

  /**
   * Check that configuration of the target named 'ruleName' in the
   * specified BUILD file fails with an error message containing
   * 'expectedErrorMessage'.
   *
   * @param packageName the package name of the generated BUILD file
   * @param ruleName the rule name for the rule in the generated BUILD file
   * @param expectedErrorMessage the expected error message.
   * @param lines the text of the rule.
   * @return the found error.
   */
  protected Event checkError(String packageName,
                             String ruleName,
                             String expectedErrorMessage,
                             String... lines) throws Exception {
    eventCollector.clear();
    reporter.removeHandler(failFastHandler); // expect errors
    ConfiguredTarget target = scratchConfiguredTarget(packageName, ruleName, lines);
    if (target != null) {
      assertWithMessage(
              "Rule '" + "//" + packageName + ":" + ruleName + "' did not contain an error")
          .that(view.hasErrors(target))
          .isTrue();
    }
    return assertContainsEvent(expectedErrorMessage);
  }

  /**
   * Check that configuration of the target named 'label' fails with an error message containing
   * 'expectedErrorMessage'.
   *
   * @param label the target name to test
   * @param expectedErrorMessage the expected error message.
   * @return the found error.
   */
  protected Event checkError(String label, String expectedErrorMessage) throws Exception {
    eventCollector.clear();
    reporter.removeHandler(failFastHandler); // expect errors
    ConfiguredTarget target = getConfiguredTarget(label);
    if (target != null) {
      assertWithMessage("Rule '" + label + "' did not contain an error")
          .that(view.hasErrors(target))
          .isTrue();
    }
    return assertContainsEvent(expectedErrorMessage);
  }

  /**
   * Checks whether loading the given target results in the specified error message.
   *
   * @param target the name of the target.
   * @param expectedErrorMessage the expected error message.
   */
  protected void checkLoadingPhaseError(String target, String expectedErrorMessage) {
    reporter.removeHandler(failFastHandler);
    // The error happens during the loading of the Skylark file so checkError doesn't work here
    assertThrows(Exception.class, () -> getTarget(target));
    assertContainsEvent(expectedErrorMessage);
  }

  /**
   * Check that configuration of the target named 'ruleName' in the
   * specified BUILD file reports a warning message ending in
   * 'expectedWarningMessage', and that no errors were reported.
   *
   * @param packageName the package name of the generated BUILD file
   * @param ruleName the rule name for the rule in the generated BUILD file
   * @param expectedWarningMessage the expected warning message.
   * @param lines the text of the rule.
   * @return the found error.
   */
  protected Event checkWarning(String packageName,
                               String ruleName,
                               String expectedWarningMessage,
                               String... lines) throws Exception {
    eventCollector.clear();
    ConfiguredTarget target = scratchConfiguredTarget(packageName, ruleName,
        lines);
    assertWithMessage("Rule '" + "//" + packageName + ":" + ruleName + "' did contain an error")
        .that(view.hasErrors(target))
        .isFalse();
    return assertContainsEvent(expectedWarningMessage);
  }

  /**
   * Given a collection of Artifacts, returns a corresponding set of strings of the form "[root]
   * [relpath]", such as "bin x/libx.a". Such strings make assertions easier to write.
   *
   * <p>The returned set preserves the order of the input.
   */
  protected Set<String> artifactsToStrings(NestedSet<? extends Artifact> artifacts) {
    return artifactsToStrings(artifacts.toList());
  }

  /**
   * Given a collection of Artifacts, returns a corresponding set of strings of the form "[root]
   * [relpath]", such as "bin x/libx.a". Such strings make assertions easier to write.
   *
   * <p>The returned set preserves the order of the input.
   */
  protected Set<String> artifactsToStrings(Iterable<? extends Artifact> artifacts) {
    return AnalysisTestUtil.artifactsToStrings(masterConfig, artifacts);
  }

  /**
   * Asserts that targetName's outputs are exactly expectedOuts.
   *
   * @param targetName The label of a rule.
   * @param expectedOuts The labels of the expected outputs of the rule.
   */
  protected void assertOuts(String targetName, String... expectedOuts) throws Exception {
    Rule ruleTarget = (Rule) getTarget(targetName);
    for (String expectedOut : expectedOuts) {
      Target outTarget = getTarget(expectedOut);
      if (!(outTarget instanceof OutputFile)) {
        fail("Target " + outTarget + " is not an output");
        assertThat(((OutputFile) outTarget).getGeneratingRule()).isSameInstanceAs(ruleTarget);
        // This ensures that the output artifact is wired up in the action graph
        getConfiguredTarget(expectedOut);
      }
    }

    Collection<OutputFile> outs = ruleTarget.getOutputFiles();
    assertWithMessage("Mismatched outputs: " + outs)
        .that(outs.size())
        .isEqualTo(expectedOuts.length);
  }

  /**
   * Asserts that there exists a configured target file for the given label.
   */
  protected void assertConfiguredTargetExists(String label) throws Exception {
    assertThat(getFileConfiguredTarget(label)).isNotNull();
  }

  /**
   * Assert that the first label and the second label are both generated
   * by the same command.
   */
  protected void assertSameGeneratingAction(String labelA, String labelB)
      throws Exception {
    assertWithMessage("Action for " + labelA + " did not match " + labelB)
        .that(getGeneratingActionForLabel(labelB))
        .isSameInstanceAs(getGeneratingActionForLabel(labelA));
  }

  protected Artifact getSourceArtifact(PathFragment rootRelativePath, Root root) {
    return view.getArtifactFactory().getSourceArtifact(rootRelativePath, root);
  }

  protected Artifact getSourceArtifact(String name) {
    return getSourceArtifact(PathFragment.create(name), Root.fromPath(rootDirectory));
  }

  /**
   * Gets a derived artifact, creating it if necessary. {@code ArtifactOwner} should be a genuine
   * {@link ConfiguredTargetKey} corresponding to a {@link ConfiguredTarget}. If called from a test
   * that does not exercise the analysis phase, the convenience methods {@link
   * #getBinArtifactWithNoOwner} or {@link #getGenfilesArtifactWithNoOwner} should be used instead.
   */
  protected final Artifact.DerivedArtifact getDerivedArtifact(
      PathFragment rootRelativePath, ArtifactRoot root, ArtifactOwner owner) {
    if ((owner instanceof ActionLookupValue.ActionLookupKey)) {
      ActionLookupValue actionLookupValue;
      try {
        actionLookupValue =
            (ActionLookupValue)
                skyframeExecutor.getEvaluatorForTesting().getExistingValue((SkyKey) owner);
      } catch (InterruptedException e) {
        throw new IllegalStateException(e);
      }
      if (actionLookupValue != null) {
        for (ActionAnalysisMetadata action : actionLookupValue.getActions()) {
          for (Artifact output : action.getOutputs()) {
            if (output.getRootRelativePath().equals(rootRelativePath)
                && output.getRoot().equals(root)) {
              return (Artifact.DerivedArtifact) output;
            }
          }
        }
      }
    }
    // Fall back: some tests don't actually need an artifact with an owner.
    return view.getArtifactFactory().getDerivedArtifact(rootRelativePath, root, owner);
  }

  /**
   * Gets a Tree Artifact for testing in the subdirectory of the {@link
   * BuildConfiguration#getBinDirectory} corresponding to the package of {@code owner}. So to
   * specify a file foo/foo.o owned by target //foo:foo, {@code packageRelativePath} should just be
   * "foo.o".
   */
  protected final Artifact getTreeArtifact(String packageRelativePath, ConfiguredTarget owner) {
    ActionLookupValue.ActionLookupKey actionLookupKey =
        ConfiguredTargetKey.of(owner, owner.getConfigurationKey(), /*isHostConfiguration=*/ false);
    return getDerivedArtifact(
        owner.getLabel().getPackageFragment().getRelative(packageRelativePath),
        getConfiguration(owner).getBinDirectory(RepositoryName.MAIN),
        actionLookupKey);
  }

  /**
   * Gets a derived Artifact for testing with path of the form
   * root/owner.getPackageFragment()/packageRelativePath.
   *
   * @see #getDerivedArtifact(PathFragment, ArtifactRoot, ArtifactOwner)
   */
  private Artifact getPackageRelativeDerivedArtifact(
      String packageRelativePath, ArtifactRoot root, ArtifactOwner owner) {
    return getDerivedArtifact(
        owner.getLabel().getPackageFragment().getRelative(packageRelativePath),
        root, owner);
  }

  /** Returns the input {@link Artifact}s to the given {@link Action} with the given exec paths. */
  protected List<Artifact> getInputs(Action owner, Collection<String> execPaths) {
    Set<String> expectedPaths = new HashSet<>(execPaths);
    List<Artifact> result = new ArrayList<>();
    for (Artifact output : owner.getInputs().toList()) {
      if (expectedPaths.remove(output.getExecPathString())) {
        result.add(output);
      }
    }
    assertWithMessage("expected paths not found in: %s", Artifact.asExecPaths(owner.getInputs()))
        .that(expectedPaths)
        .isEmpty();
    return result;
  }

  /**
   * Gets a derived Artifact for testing in the {@link BuildConfiguration#getBinDirectory}. This
   * method should only be used for tests that do no analysis, and so there is no ConfiguredTarget
   * to own this artifact. If the test runs the analysis phase, {@link #getBinArtifact(String,
   * ConfiguredTarget)} or its convenience methods should be used instead.
   */
  protected Artifact.DerivedArtifact getBinArtifactWithNoOwner(String rootRelativePath) {
    return getDerivedArtifact(PathFragment.create(rootRelativePath),
        targetConfig.getBinDirectory(RepositoryName.MAIN),
        ActionsTestUtil.NULL_ARTIFACT_OWNER);
  }

  /**
   * Gets a derived Artifact for testing in the subdirectory of the {@link
   * BuildConfiguration#getBinDirectory} corresponding to the package of {@code owner}. So to
   * specify a file foo/foo.o owned by target //foo:foo, {@code packageRelativePath} should just be
   * "foo.o".
   */
  protected final Artifact getBinArtifact(String packageRelativePath, ConfiguredTarget owner) {
    return getPackageRelativeDerivedArtifact(
        packageRelativePath,
        getConfiguration(owner).getBinDirectory(RepositoryName.MAIN),
        ConfiguredTargetKey.of(
            owner, skyframeExecutor.getConfiguration(reporter, owner.getConfigurationKey())));
  }

  /**
   * Gets a derived Artifact for testing in the subdirectory of the {@link
   * BuildConfiguration#getBinDirectory} corresponding to the package of {@code owner}, where the
   * given artifact belongs to the given ConfiguredTarget together with the given Aspect. So to
   * specify a file foo/foo.o owned by target //foo:foo with an aspect from FooAspect, {@code
   * packageRelativePath} should just be "foo.o", and aspectOfOwner should be FooAspect.class. This
   * method is necessary when an Aspect of the target, not the target itself, is creating an
   * Artifact.
   */
  protected Artifact getBinArtifact(
      String packageRelativePath, ConfiguredTarget owner, AspectClass creatingAspectFactory) {
    return getBinArtifact(
        packageRelativePath, owner, creatingAspectFactory, AspectParameters.EMPTY);
  }

  /**
   * Gets a derived Artifact for testing in the subdirectory of the {@link
   * BuildConfiguration#getBinDirectory} corresponding to the package of {@code owner}, where the
   * given artifact belongs to the given ConfiguredTarget together with the given Aspect. So to
   * specify a file foo/foo.o owned by target //foo:foo with an aspect from FooAspect, {@code
   * packageRelativePath} should just be "foo.o", and aspectOfOwner should be FooAspect.class. This
   * method is necessary when an Aspect of the target, not the target itself, is creating an
   * Artifact.
   */
  protected Artifact getBinArtifact(
      String packageRelativePath,
      ConfiguredTarget owner,
      AspectClass creatingAspectFactory,
      AspectParameters parameters) {
    return getPackageRelativeDerivedArtifact(
        packageRelativePath,
        getConfiguration(owner).getBinDirectory(RepositoryName.MAIN),
        (AspectValue.AspectKey)
            AspectValue.createAspectKey(
                    owner.getLabel(),
                    getConfiguration(owner),
                    new AspectDescriptor(creatingAspectFactory, parameters),
                    getConfiguration(owner))
                .argument());
  }

  /**
   * Gets a derived Artifact for testing in the {@link BuildConfiguration#getGenfilesDirectory}.
   * This method should only be used for tests that do no analysis, and so there is no
   * ConfiguredTarget to own this artifact. If the test runs the analysis phase, {@link
   * #getGenfilesArtifact(String, ConfiguredTarget)} or its convenience methods should be used
   * instead.
   */
  protected Artifact getGenfilesArtifactWithNoOwner(String rootRelativePath) {
    return getDerivedArtifact(PathFragment.create(rootRelativePath),
        targetConfig.getGenfilesDirectory(RepositoryName.MAIN),
        ActionsTestUtil.NULL_ARTIFACT_OWNER);
  }

  /**
   * Gets a derived Artifact for testing in the subdirectory of the {@link
   * BuildConfiguration#getGenfilesDirectory} corresponding to the package of {@code owner}. So to
   * specify a file foo/foo.o owned by target //foo:foo, {@code packageRelativePath} should just be
   * "foo.o".
   */
  protected Artifact getGenfilesArtifact(String packageRelativePath, String owner) {
    BuildConfiguration config = getConfiguration(owner);
    return getGenfilesArtifact(
        packageRelativePath, ConfiguredTargetKey.of(makeLabel(owner), config), config);
  }

  /**
   * Gets a derived Artifact for testing in the subdirectory of the {@link
   * BuildConfiguration#getGenfilesDirectory} corresponding to the package of {@code owner}. So to
   * specify a file foo/foo.o owned by target //foo:foo, {@code packageRelativePath} should just be
   * "foo.o".
   */
  protected Artifact getGenfilesArtifact(String packageRelativePath, ConfiguredTarget owner) {
    BuildConfiguration configuration =
        skyframeExecutor.getConfiguration(reporter, owner.getConfigurationKey());
    ConfiguredTargetKey configKey = ConfiguredTargetKey.of(owner, configuration);
    return getGenfilesArtifact(packageRelativePath, configKey, configuration);
  }

  /**
   * Gets a derived Artifact for testing in the subdirectory of the {@link
   * BuildConfiguration#getGenfilesDirectory} corresponding to the package of {@code owner}, where
   * the given artifact belongs to the given ConfiguredTarget together with the given Aspect. So to
   * specify a file foo/foo.o owned by target //foo:foo with an apsect from FooAspect, {@code
   * packageRelativePath} should just be "foo.o", and aspectOfOwner should be FooAspect.class. This
   * method is necessary when an Apsect of the target, not the target itself, is creating an
   * Artifact.
   */
  protected Artifact getGenfilesArtifact(
      String packageRelativePath, ConfiguredTarget owner, NativeAspectClass creatingAspectFactory) {
    return getGenfilesArtifact(
        packageRelativePath, owner, creatingAspectFactory, AspectParameters.EMPTY);
  }

  protected Artifact getGenfilesArtifact(
      String packageRelativePath,
      ConfiguredTarget owner,
      NativeAspectClass creatingAspectFactory,
      AspectParameters params) {
    return getPackageRelativeDerivedArtifact(
        packageRelativePath,
        getConfiguration(owner)
            .getGenfilesDirectory(owner.getLabel().getPackageIdentifier().getRepository()),
        getOwnerForAspect(owner, creatingAspectFactory, params));
  }

  /**
   * Gets a derived Artifact for testing in the subdirectory of the {@link
   * BuildConfiguration#getGenfilesDirectory} corresponding to the package of {@code owner}. So to
   * specify a file foo/foo.o owned by target //foo:foo, {@code packageRelativePath} should just be
   * "foo.o".
   */
  private Artifact getGenfilesArtifact(
      String packageRelativePath, ArtifactOwner owner, BuildConfiguration config) {
    return getPackageRelativeDerivedArtifact(
        packageRelativePath, config.getGenfilesDirectory(RepositoryName.MAIN), owner);
  }

  protected AspectValue.AspectKey getOwnerForAspect(
      ConfiguredTarget owner, NativeAspectClass creatingAspectFactory, AspectParameters params) {
    return (AspectValue.AspectKey)
        AspectValue.createAspectKey(
                owner.getLabel(),
                getConfiguration(owner),
                new AspectDescriptor(creatingAspectFactory, params),
                getConfiguration(owner))
            .argument();
  }

  /**
   * Gets a derived Artifact for testing in the subdirectory of the {@link
   * BuildConfiguration#getIncludeDirectory} corresponding to the package of {@code owner}. So to
   * specify a file foo/foo.o owned by target //foo:foo, {@code packageRelativePath} should just be
   * "foo.h".
   */
  protected Artifact getIncludeArtifact(String packageRelativePath, String owner) {
    return getIncludeArtifact(packageRelativePath, makeConfiguredTargetKey(owner));
  }

  /**
   * Gets a derived Artifact for testing in the subdirectory of the {@link
   * BuildConfiguration#getIncludeDirectory} corresponding to the package of {@code owner}. So to
   * specify a file foo/foo.o owned by target //foo:foo, {@code packageRelativePath} should just be
   * "foo.h".
   */
  protected Artifact getIncludeArtifact(String packageRelativePath, ArtifactOwner owner) {
    return getPackageRelativeDerivedArtifact(packageRelativePath,
        targetConfig.getIncludeDirectory(owner.getLabel().getPackageIdentifier().getRepository()),
        owner);
  }

  /**
   * @return a shared artifact at the binary-root relative path {@code rootRelativePath} owned by
   *         {@code owner}.
   *
   * @param rootRelativePath the binary-root relative path of the artifact.
   * @param owner the artifact's owner.
   */
  protected Artifact getSharedArtifact(String rootRelativePath, ConfiguredTarget owner) {
    return getDerivedArtifact(
        PathFragment.create(rootRelativePath),
        targetConfig.getBinDirectory(RepositoryName.MAIN),
        ConfiguredTargetKey.of(
            owner, skyframeExecutor.getConfiguration(reporter, owner.getConfigurationKey())));
  }

  protected Action getGeneratingActionForLabel(String label) throws Exception {
    return getGeneratingAction(getFileConfiguredTarget(label).getArtifact());
  }

  /**
   * Strips the C++-contributed prefix out of an output path when tests are run with trimmed
   * configurations. e.g. turns "bazel-out/gcc-X-glibc-Y-k8-fastbuild/ to "bazel-out/fastbuild/".
   *
   * <p>This should be used for targets use configurations with C++ fragments.
   */
  protected String stripCppPrefixForTrimmedConfigs(String outputPath) {
    return targetConfig.trimConfigurations()
        ? AnalysisTestUtil.OUTPUT_PATH_CPP_PREFIX_PATTERN.matcher(outputPath).replaceFirst("")
        : outputPath;
  }

  protected String fileName(Artifact artifact) {
    return artifact.getExecPathString();
  }

  protected String fileName(FileConfiguredTarget target) {
    return fileName(target.getArtifact());
  }

  protected String fileName(String name) throws Exception {
    return fileName(getFileConfiguredTarget(name));
  }

  protected Path getOutputPath() {
    return directories.getOutputPath(ruleClassProvider.getRunfilesPrefix());
  }

  /**
   * Verifies whether the rule checks the 'srcs' attribute validity.
   *
   * <p>At the call site it expects the {@code packageName} to contain:
   * <ol>
   *   <li>{@code :gvalid} - genrule that outputs a valid file</li>
   *   <li>{@code :ginvalid} - genrule that outputs an invalid file</li>
   *   <li>{@code :gmix} - genrule that outputs a mix of valid and invalid
   *       files</li>
   *   <li>{@code :valid} - rule of type {@code ruleType} that has a valid
   *       file, {@code :gvalid} and {@code :gmix} in the srcs</li>
   *   <li>{@code :invalid} - rule of type {@code ruleType} that has an invalid
   *       file, {@code :ginvalid} in the srcs</li>
   *   <li>{@code :mix} - rule of type {@code ruleType} that has a valid and an
   *       invalid file in the srcs</li>
   * </ol>
   *
   * @param packageName the package where the rules under test are located
   * @param ruleType rules under test types
   * @param expectedTypes expected file types
   */
  protected void assertSrcsValidityForRuleType(String packageName, String ruleType,
      String expectedTypes) throws Exception {
    reporter.removeHandler(failFastHandler);
    String descriptionSingle = ruleType + " srcs file (expected " + expectedTypes + ")";
    String descriptionPlural = ruleType + " srcs files (expected " + expectedTypes + ")";
    String descriptionPluralFile = "(expected " + expectedTypes + ")";
    assertSrcsValidity(ruleType, packageName + ":valid", false,
        "need at least one " + descriptionSingle,
        "'" + packageName + ":gvalid' does not produce any " + descriptionPlural,
        "'" + packageName + ":gmix' does not produce any " + descriptionPlural);
    assertSrcsValidity(ruleType, packageName + ":invalid", true,
        "source file '" + packageName + ":a.foo' is misplaced here " + descriptionPluralFile,
        "'" + packageName + ":ginvalid' does not produce any " + descriptionPlural);
    assertSrcsValidity(ruleType, packageName + ":mix", true,
        "'" + packageName + ":a.foo' does not produce any " + descriptionPlural);
  }

  protected void assertSrcsValidity(String ruleType, String targetName, boolean expectedError,
      String... expectedMessages) throws Exception{
    ConfiguredTarget target = getConfiguredTarget(targetName);
    if (expectedError) {
      assertThat(view.hasErrors(target)).isTrue();
      for (String expectedMessage : expectedMessages) {
        String message = "in srcs attribute of " + ruleType + " rule " + targetName + ": "
            + expectedMessage;
        assertContainsEvent(message);
      }
    } else {
      assertThat(view.hasErrors(target)).isFalse();
      for (String expectedMessage : expectedMessages) {
        String message = "in srcs attribute of " + ruleType + " rule " + target.getLabel() + ": "
            + expectedMessage;
        assertDoesNotContainEvent(message);
      }
    }
  }

  protected static ConfiguredAttributeMapper getMapperFromConfiguredTargetAndTarget(
      ConfiguredTargetAndData ctad) {
    return ConfiguredAttributeMapper.of(
        (Rule) ctad.getTarget(),
        ((RuleConfiguredTarget) ctad.getConfiguredTarget()).getConfigConditions());
  }

  public static Label makeLabel(String label) {
    try {
      return Label.parseAbsolute(label, ImmutableMap.of());
    } catch (LabelSyntaxException e) {
      throw new IllegalStateException(e);
    }
  }

  private ConfiguredTargetKey makeConfiguredTargetKey(String label) {
    return ConfiguredTargetKey.of(makeLabel(label), getConfiguration(label));
  }

  protected static List<String> actionInputsToPaths(NestedSet<? extends ActionInput> actionInputs) {
    return ImmutableList.copyOf(
        Iterables.transform(
            actionInputs.toList(), (actionInput) -> actionInput.getExecPathString()));
  }

  /**
   * Utility method for asserting that the contents of one collection are the
   * same as those in a second plus some set of common elements.
   */
  protected void assertSameContentsWithCommonElements(Iterable<String> artifacts,
      String[] expectedInputs, Iterable<String> common) {
    assertThat(Iterables.concat(Lists.newArrayList(expectedInputs), common))
        .containsExactlyElementsIn(artifacts);
  }

  /**
   * Utility method for asserting that a list contains the elements of a
   * sublist. This is useful for checking that a list of arguments contains a
   * particular set of arguments.
   */
  protected void assertContainsSublist(List<String> list, List<String> sublist) {
    assertContainsSublist(null, list, sublist);
  }

  /**
   * Utility method for asserting that a list contains the elements of a
   * sublist. This is useful for checking that a list of arguments contains a
   * particular set of arguments.
   */
  protected void assertContainsSublist(String message, List<String> list, List<String> sublist) {
    if (Collections.indexOfSubList(list, sublist) == -1) {
      fail((message == null ? "" : (message + ' '))
          + "expected: <" + list + "> to contain sublist: <" + sublist + ">");
    }
  }

  protected void assertContainsSelfEdgeEvent(String label) {
    assertContainsEvent(label + " [self-edge]");
  }

  protected NestedSet<Artifact> collectRunfiles(ConfiguredTarget target) {
    RunfilesProvider runfilesProvider = target.getProvider(RunfilesProvider.class);
    if (runfilesProvider != null) {
      return runfilesProvider.getDefaultRunfiles().getAllArtifacts();
    } else {
      return Runfiles.EMPTY.getAllArtifacts();
    }
  }

  protected NestedSet<Artifact> getFilesToBuild(TransitiveInfoCollection target) {
    return target.getProvider(FileProvider.class).getFilesToBuild();
  }

  /**
   * Returns all extra actions for that target (no transitive actions), no duplicate actions.
   */
  protected ImmutableList<Action> getExtraActionActions(ConfiguredTarget target) {
    LinkedHashSet<Action> result = new LinkedHashSet<>();
    for (Artifact artifact : getExtraActionArtifacts(target).toList()) {
      result.add(getGeneratingAction(artifact));
    }
    return ImmutableList.copyOf(result);
  }

  /**
   * Returns all extra actions for that target (including transitive actions).
   */
  protected ImmutableList<ExtraAction> getTransitiveExtraActionActions(ConfiguredTarget target) {
    ImmutableList.Builder<ExtraAction> result = new ImmutableList.Builder<>();
    for (Artifact artifact :
        target
            .getProvider(ExtraActionArtifactsProvider.class)
            .getTransitiveExtraActionArtifacts()
            .toList()) {
      Action action = getGeneratingAction(artifact);
      if (action instanceof ExtraAction) {
        result.add((ExtraAction) action);
      }
    }
    return result.build();
  }

  protected ImmutableList<Action> getFilesToBuildActions(ConfiguredTarget target) {
    List<Action> result = new ArrayList<>();
    for (Artifact artifact : getFilesToBuild(target).toList()) {
      Action action = getGeneratingAction(artifact);
      if (action != null) {
        result.add(action);
      }
    }
    return ImmutableList.copyOf(result);
  }

  protected NestedSet<Artifact> getOutputGroup(
      TransitiveInfoCollection target, String outputGroup) {
    OutputGroupInfo provider = OutputGroupInfo.get(target);
    return provider == null
        ? NestedSetBuilder.<Artifact>emptySet(Order.STABLE_ORDER)
        : provider.getOutputGroup(outputGroup);
  }

  protected NestedSet<Artifact.DerivedArtifact> getExtraActionArtifacts(ConfiguredTarget target) {
    return target.getProvider(ExtraActionArtifactsProvider.class).getExtraActionArtifacts();
  }

  protected Artifact getExecutable(String label) throws Exception {
    return getConfiguredTarget(label).getProvider(FilesToRunProvider.class).getExecutable();
  }

  protected Artifact getExecutable(TransitiveInfoCollection target) {
    return target.getProvider(FilesToRunProvider.class).getExecutable();
  }

  protected NestedSet<Artifact> getFilesToRun(TransitiveInfoCollection target) {
    return target.getProvider(FilesToRunProvider.class).getFilesToRun();
  }

  protected NestedSet<Artifact> getFilesToRun(Label label) throws Exception {
    return getConfiguredTarget(label, targetConfig)
        .getProvider(FilesToRunProvider.class).getFilesToRun();
  }

  protected NestedSet<Artifact> getFilesToRun(String label) throws Exception {
    return getConfiguredTarget(label).getProvider(FilesToRunProvider.class).getFilesToRun();
  }

  protected RunfilesSupport getRunfilesSupport(String label) throws Exception {
    return getConfiguredTarget(label).getProvider(FilesToRunProvider.class).getRunfilesSupport();
  }

  protected RunfilesSupport getRunfilesSupport(TransitiveInfoCollection target) {
    return target.getProvider(FilesToRunProvider.class).getRunfilesSupport();
  }

  protected static Runfiles getDefaultRunfiles(ConfiguredTarget target) {
    return target.getProvider(RunfilesProvider.class).getDefaultRunfiles();
  }

  protected static Runfiles getDataRunfiles(ConfiguredTarget target) {
    return target.getProvider(RunfilesProvider.class).getDataRunfiles();
  }

  protected BuildConfiguration getTargetConfiguration() {
    return Iterables.getOnlyElement(masterConfig.getTargetConfigurations());
  }

  protected BuildConfiguration getHostConfiguration() {
    return masterConfig.getHostConfiguration();
  }

  /**
   * Returns the configuration created by applying the given transition to the source configuration.
   *
   * @throws AssertionError if the transition couldn't be evaluated
   */
  protected BuildConfiguration getConfiguration(
      BuildConfiguration fromConfig, PatchTransition transition) throws InterruptedException {
    if (transition == NoTransition.INSTANCE) {
      return fromConfig;
    } else if (transition == NullTransition.INSTANCE) {
      return null;
    } else {
      try {
        return skyframeExecutor.getConfigurationForTesting(
            reporter, fromConfig.fragmentClasses(), transition.patch(fromConfig.getOptions()));
      } catch (OptionsParsingException | InvalidConfigurationException e) {
        throw new AssertionError(e);
      }
    }
  }

  private BuildConfiguration getConfiguration(String label) {
    BuildConfiguration config;
    try {
      config = getConfiguration(getConfiguredTarget(label));
      config = view.getConfigurationForTesting(getTarget(label), config, reporter);
    } catch (LabelSyntaxException e) {
      throw new IllegalArgumentException(e);
    } catch (Exception e) {
      // TODO(b/36585204): Clean this up
      throw new RuntimeException(e);
    }
    return config;
  }

  protected final BuildConfiguration getConfiguration(ConfiguredTarget ct) {
    return skyframeExecutor.getConfiguration(reporter, ct.getConfigurationKey());
  }

  /** Returns an attribute value retriever for the given rule for the target configuration. */
  protected AttributeMap attributes(RuleConfiguredTarget ct) {
    ConfiguredTargetAndData ctad;
    try {
      ctad = getConfiguredTargetAndData(ct.getLabel().toString());
    } catch (LabelSyntaxException
        | StarlarkTransition.TransitionException
        | InvalidConfigurationException e) {
      throw new RuntimeException(e);
    }
    return getMapperFromConfiguredTargetAndTarget(ctad);
  }

  protected AttributeMap attributes(ConfiguredTarget rule) {
    return attributes((RuleConfiguredTarget) rule);
  }

  protected void useLoadingOptions(String... options) throws OptionsParsingException {
    customLoadingOptions = Options.parse(LoadingOptions.class, options).getOptions();
  }

  protected AnalysisResult update(List<String> targets,
      boolean keepGoing,
      int loadingPhaseThreads,
      boolean doAnalysis,
      EventBus eventBus) throws Exception {
    return update(
        targets, ImmutableList.<String>of(), keepGoing, loadingPhaseThreads, doAnalysis, eventBus);
  }

  protected AnalysisResult update(
      List<String> targets,
      List<String> aspects,
      boolean keepGoing,
      int loadingPhaseThreads,
      boolean doAnalysis,
      EventBus eventBus)
      throws Exception {

    LoadingOptions loadingOptions =
        customLoadingOptions == null
            ? Options.getDefaults(LoadingOptions.class)
            : customLoadingOptions;

    AnalysisOptions viewOptions = Options.getDefaults(AnalysisOptions.class);

    TargetPatternPhaseValue loadingResult =
        skyframeExecutor.loadTargetPatternsWithFilters(
            reporter,
            targets,
            PathFragment.EMPTY_FRAGMENT,
            loadingOptions,
            loadingPhaseThreads,
            keepGoing,
            /*determineTests=*/ false);
    if (!doAnalysis) {
      // TODO(bazel-team): What's supposed to happen in this case?
      return null;
    }
    return view.update(
        loadingResult,
        targetConfig.getOptions(),
        /* multiCpu= */ ImmutableSet.of(),
        aspects,
        viewOptions,
        keepGoing,
        loadingPhaseThreads,
        AnalysisTestUtil.TOP_LEVEL_ARTIFACT_CONTEXT,
        reporter,
        eventBus);
  }

  protected static Predicate<Artifact> artifactNamed(final String name) {
    return new Predicate<Artifact>() {
      @Override
      public boolean apply(Artifact input) {
        return name.equals(input.prettyPrint());
      }
    };
  }

  /**
   * Utility method for tests. Converts an array of strings into a set of labels.
   *
   * @param strings the set of strings to be converted to labels.
   * @throws LabelSyntaxException if there are any syntax errors in the strings.
   */
  public static Set<Label> asLabelSet(String... strings) throws LabelSyntaxException {
    return asLabelSet(ImmutableList.copyOf(strings));
  }

  /**
   * Utility method for tests. Converts an array of strings into a set of labels.
   *
   * @param strings the set of strings to be converted to labels.
   * @throws LabelSyntaxException if there are any syntax errors in the strings.
   */
  public static Set<Label> asLabelSet(Iterable<String> strings) throws LabelSyntaxException {
    Set<Label> result = Sets.newTreeSet();
    for (String s : strings) {
      result.add(Label.parseAbsolute(s, ImmutableMap.of()));
    }
    return result;
  }

  protected String getErrorMsgNoGoodFiles(String attrName, String ruleType, String ruleName,
      String depRuleName) {
    return "in " + attrName + " attribute of " + ruleType + " rule " + ruleName + ": '"
        + depRuleName + "' does not produce any " + ruleType + " " + attrName + " files";
  }

  protected String getErrorMsgMisplacedFiles(String attrName, String ruleType, String ruleName,
      String fileName) {
    return "in " + attrName + " attribute of " + ruleType + " rule " + ruleName + ": source file '"
        + fileName + "' is misplaced here";
  }

  protected String getErrorNonExistingTarget(String attrName, String ruleType, String ruleName,
      String targetName) {
    return "in " + attrName + " attribute of " + ruleType + " rule " + ruleName + ": target '"
        + targetName + "' does not exist";
  }

  protected String getErrorNonExistingRule(String attrName, String ruleType, String ruleName,
      String targetName) {
    return "in " + attrName + " attribute of " + ruleType + " rule " + ruleName + ": rule '"
        + targetName + "' does not exist";
  }

  protected String getErrorMsgMisplacedRules(String attrName, String ruleType, String ruleName,
      String depRuleType, String depRuleName) {
    return "in " + attrName + " attribute of " + ruleType + " rule " + ruleName + ": "
        + depRuleType + " rule '" + depRuleName + "' is misplaced here";
  }

  protected String getErrorMsgNonEmptyList(String attrName, String ruleType, String ruleName) {
    return "in " + attrName + " attribute of " + ruleType + " rule " + ruleName + ": attribute "
        + "must be non empty";
  }

  protected String getErrorMsgMandatoryMissing(String attrName, String ruleType) {
    return "missing value for mandatory attribute '" + attrName + "' in '" + ruleType + "' rule";
  }

  protected String getErrorMsgWrongAttributeValue(String value, String... expected) {
    return String.format("has to be one of %s instead of '%s'",
        StringUtil.joinEnglishList(ImmutableSet.copyOf(expected), "or", "'"), value);
  }

  protected String getErrorMsgMandatoryProviderMissing(String offendingRule, String providerName) {
    return String.format("'%s' does not have mandatory providers: '%s'",
        offendingRule, providerName);
  }

  /**
   * Utility method for tests that result in errors early during
   * package loading. Given the name of the package for the test,
   * and the rules for the build file, create a scratch file, load
   * the build file, and produce the package.
   * @param packageName the name of the package for the build file
   * @param lines the rules for the build file as an array of strings
   * @return the loaded package from the populated package cache
   * @throws Exception if there is an error creating the temporary files
   *    for the test.
   */
  protected com.google.devtools.build.lib.packages.Package createScratchPackageForImplicitCycle(
      String packageName, String... lines) throws Exception {
    eventCollector.clear();
    reporter.removeHandler(failFastHandler);
    scratch.file("" + packageName + "/BUILD", lines);
    return getPackageManager()
        .getPackage(reporter, PackageIdentifier.createInMainRepo(packageName));
  }

  /**
   * A stub analysis environment.
   */
  protected class StubAnalysisEnvironment implements AnalysisEnvironment {

    @Override
    public void registerAction(ActionAnalysisMetadata... action) {
      throw new UnsupportedOperationException();
    }

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

    @Override
    public Artifact getConstantMetadataArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
      throw new UnsupportedOperationException();
    }

    @Override
    public SpecialArtifact getTreeArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
      throw new UnsupportedOperationException();
    }

    @Override
    public SpecialArtifact getSymlinkArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
      throw new UnsupportedOperationException();
    }

    @Override
    public ExtendedEventHandler getEventHandler() {
      return reporter;
    }

    @Override
    public MiddlemanFactory getMiddlemanFactory() {
      throw new UnsupportedOperationException();
    }

    @Override
    public Action getLocalGeneratingAction(Artifact artifact) {
      throw new UnsupportedOperationException();
    }

    @Override
    public ImmutableList<ActionAnalysisMetadata> getRegisteredActions() {
      throw new UnsupportedOperationException();
    }

    @Override
    public SkyFunction.Environment getSkyframeEnv() {
      throw new UnsupportedOperationException();
    }

    @Override
    public StarlarkSemantics getSkylarkSemantics() {
      return starlarkSemanticsOptions.toSkylarkSemantics();
    }

    @Override
    public Artifact getFilesetArtifact(PathFragment rootRelativePath, ArtifactRoot root) {
      throw new UnsupportedOperationException();
    }

    @Override
    public Artifact.DerivedArtifact getDerivedArtifact(
        PathFragment rootRelativePath, ArtifactRoot root) {
      throw new UnsupportedOperationException();
    }

    @Override
    public Artifact.DerivedArtifact getDerivedArtifact(
        PathFragment rootRelativePath, ArtifactRoot root, boolean contentBasedPath) {
      throw new UnsupportedOperationException();
    }

    @Override
    public Artifact getStableWorkspaceStatusArtifact() {
      throw new UnsupportedOperationException();
    }

    @Override
    public Artifact getVolatileWorkspaceStatusArtifact() {
      throw new UnsupportedOperationException();
    }

    @Override
    public ImmutableList<Artifact> getBuildInfo(
        boolean stamp, BuildInfoKey key, BuildConfiguration config) {
      throw new UnsupportedOperationException();
    }

    @Override
    public ActionLookupValue.ActionLookupKey getOwner() {
      throw new UnsupportedOperationException();
    }

    @Override
    public ImmutableSet<Artifact> getOrphanArtifacts() {
      throw new UnsupportedOperationException();
    }

    @Override
    public ImmutableSet<Artifact> getTreeArtifactsConflictingWithFiles() {
      throw new UnsupportedOperationException();
    }

    @Override
    public ActionKeyContext getActionKeyContext() {
      return actionKeyContext;
    }
  }

  protected Iterable<String> baselineCoverageArtifactBasenames(ConfiguredTarget target)
      throws Exception {
    ImmutableList.Builder<String> basenames = ImmutableList.builder();
    for (Artifact baselineCoverage :
        target
            .get(InstrumentedFilesInfo.SKYLARK_CONSTRUCTOR)
            .getBaselineCoverageArtifacts()
            .toList()) {
      BaselineCoverageAction baselineAction =
          (BaselineCoverageAction) getGeneratingAction(baselineCoverage);
      ByteArrayOutputStream bytes = new ByteArrayOutputStream();
      baselineAction.newDeterministicWriter(ActionsTestUtil.createContext(reporter))
          .writeOutputFile(bytes);

      for (String line : new String(bytes.toByteArray(), StandardCharsets.UTF_8).split("\n")) {
        if (line.startsWith("SF:")) {
          String basename = line.substring(line.lastIndexOf('/') + 1);
          basenames.add(basename);
        }
      }
    }
    return basenames.build();
  }

  /**
   * Finds an artifact in the transitive closure of a set of other artifacts by following a path
   * based on artifact name suffixes.
   *
   * <p>This selects the first artifact in the input set that matches the first suffix, then selects
   * the first artifact in the inputs of its generating action that matches the second suffix etc.,
   * and repeats this until the supplied suffixes run out.
   */
  protected Artifact artifactByPath(NestedSet<Artifact> artifacts, String... suffixes) {
    return artifactByPath(artifacts.toList(), suffixes);
  }

  /**
   * Finds an artifact in the transitive closure of a set of other artifacts by following a path
   * based on artifact name suffixes.
   *
   * <p>This selects the first artifact in the input set that matches the first suffix, then selects
   * the first artifact in the inputs of its generating action that matches the second suffix etc.,
   * and repeats this until the supplied suffixes run out.
   */
  protected Artifact artifactByPath(Iterable<Artifact> artifacts, String... suffixes) {
    Artifact artifact = getFirstArtifactEndingWith(artifacts, suffixes[0]);
    Action action = null;
    for (int i = 1; i < suffixes.length; i++) {
      if (artifact == null) {
        if (action == null) {
          throw new IllegalStateException("No suffix " + suffixes[0] + " among artifacts: "
              + ActionsTestUtil.baseArtifactNames(artifacts));
        } else {
          throw new IllegalStateException("No suffix " + suffixes[i]
              + " among inputs of action " + action.describe() + ": "
              + ActionsTestUtil.baseArtifactNames(artifacts));
        }
      }

      action = getGeneratingAction(artifact);
      artifacts = action.getInputs().toList();
      artifact = getFirstArtifactEndingWith(artifacts, suffixes[i]);
    }

    return artifact;
  }

  /**
   * Retrieves an instance of {@code PseudoAction} that is shadowed by an extra action
   * @param targetLabel Label of the target with an extra action
   * @param actionListenerLabel Label of the action listener
   */
  protected PseudoAction<?> getPseudoActionViaExtraAction(
      String targetLabel, String actionListenerLabel) throws Exception {
    useConfiguration(String.format("--experimental_action_listener=%s", actionListenerLabel));

    ConfiguredTarget target = getConfiguredTarget(targetLabel);
    List<Action> actions = getExtraActionActions(target);

    assertThat(actions).isNotNull();
    assertThat(actions).hasSize(2);

    ExtraAction extraAction = null;

    for (Action action : actions) {
      if (action instanceof ExtraAction) {
        extraAction = (ExtraAction) action;
        break;
      }
    }

    assertWithMessage(actions.toString()).that(extraAction).isNotNull();

    Action pseudoAction = extraAction.getShadowedAction();

    assertThat(pseudoAction).isInstanceOf(PseudoAction.class);
    assertThat(pseudoAction.getPrimaryOutput().getExecPathString())
        .isEqualTo(
            String.format(
                "%s%s.extra_action_dummy",
                targetConfig.getGenfilesFragment(), convertLabelToPath(targetLabel)));

    return (PseudoAction<?>) pseudoAction;
  }

  /**
   * Converts the given label to an output path where double slashes and colons are
   * replaced with single slashes
   * @param label
   */
  private String convertLabelToPath(String label) {
    return label.replace(':', '/').substring(1);
  }

  protected final String getImplicitOutputPath(
      ConfiguredTarget target, SafeImplicitOutputsFunction outputFunction) {
    Rule rule;
    try {
      rule = (Rule) skyframeExecutor.getPackageManager().getTarget(reporter, target.getLabel());
    } catch (NoSuchPackageException | NoSuchTargetException | InterruptedException e) {
      throw new IllegalStateException(e);
    }
    RawAttributeMapper attr = RawAttributeMapper.of(rule.getAssociatedRule());

    return Iterables.getOnlyElement(outputFunction.getImplicitOutputs(eventCollector, attr));
  }

  /**
   * Gets the artifact whose name is derived from {@code outputFunction}. Despite the name, this can
   * be called for artifacts that are not declared as implicit outputs: it just finds the artifact
   * inside the configured target by calling {@link #getBinArtifact(String, ConfiguredTarget)} on
   * the result of the {@code outputFunction}.
   */
  protected final Artifact getImplicitOutputArtifact(
      ConfiguredTarget target, SafeImplicitOutputsFunction outputFunction) {
    return getBinArtifact(getImplicitOutputPath(target, outputFunction), target);
  }

  public Path getExecRoot() {
    return directories.getExecRoot(ruleClassProvider.getRunfilesPrefix());
  }

  /** Returns true iff commandLine contains the option --flagName followed by arg. */
  protected static boolean containsFlag(String flagName, String arg, Iterable<String> commandLine) {
    Iterator<String> iterator = commandLine.iterator();
    while (iterator.hasNext()) {
      if (flagName.equals(iterator.next()) && iterator.hasNext() && arg.equals(iterator.next())) {
        return true;
      }
    }
    return false;
  }

  /** Returns the list of arguments in commandLine that follow after --flagName. */
  protected static ImmutableList<String> flagValue(String flagName, Iterable<String> commandLine) {
    ImmutableList.Builder<String> resultBuilder = ImmutableList.builder();
    Iterator<String> iterator = commandLine.iterator();
    boolean found = false;
    while (iterator.hasNext()) {
      String val = iterator.next();
      if (found) {
        if (val.startsWith("--")) {
          break;
        }
        resultBuilder.add(val);
      } else if (flagName.equals(val)) {
        found = true;
      }
    }
    Preconditions.checkArgument(found);
    return resultBuilder.build();
  }

  /** Creates instances of {@link ActionExecutionContext} consistent with test case. */
  public class ActionExecutionContextBuilder {
    private MetadataProvider actionInputFileCache = null;
    private TreeMap<String, String> clientEnv = new TreeMap<>();
    private ArtifactExpander artifactExpander = null;

    public ActionExecutionContextBuilder setMetadataProvider(
        MetadataProvider actionInputFileCache) {
      this.actionInputFileCache = actionInputFileCache;
      return this;
    }

    public ActionExecutionContextBuilder setArtifactExpander(ArtifactExpander artifactExpander) {
      this.artifactExpander = artifactExpander;
      return this;
    }

    public ActionExecutionContext build() {
      return new ActionExecutionContext(
          new DummyExecutor(fileSystem, getExecRoot()),
          actionInputFileCache,
          /*actionInputPrefetcher=*/ null,
          actionKeyContext,
          /*metadataHandler=*/ null,
          LostInputsCheck.NONE,
          actionLogBufferPathGenerator.generate(ArtifactPathResolver.IDENTITY),
          reporter,
          clientEnv,
          /*topLevelFilesets=*/ ImmutableMap.of(),
          artifactExpander,
          /*actionFileSystem=*/ null,
          /*skyframeDepsResult*/ null);
    }
  }
}
