// 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 org.junit.Assert.assertThrows;
import static org.junit.Assert.fail;

import com.google.common.base.Ascii;
import com.google.common.base.Preconditions;
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.ActionLookupKey;
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.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.BuildOptionsView;
import com.google.devtools.build.lib.analysis.config.CoreOptions.ConfigsMode;
import com.google.devtools.build.lib.analysis.config.Fragment;
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.starlark.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.NestedSetExpander;
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.PackageValidator;
import com.google.devtools.build.lib.packages.RawAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.packages.semantics.BuildLanguageOptions;
import com.google.devtools.build.lib.packages.util.MockToolsConfig;
import com.google.devtools.build.lib.pkgcache.LoadingOptions;
import com.google.devtools.build.lib.pkgcache.PackageManager;
import com.google.devtools.build.lib.pkgcache.PackageOptions;
import com.google.devtools.build.lib.pkgcache.PathPackageLocator;
import com.google.devtools.build.lib.rules.repository.RepositoryDelegatorFunction;
import com.google.devtools.build.lib.skyframe.AspectValueKey;
import com.google.devtools.build.lib.skyframe.AspectValueKey.AspectKey;
import com.google.devtools.build.lib.skyframe.BazelSkyframeExecutorConstants;
import com.google.devtools.build.lib.skyframe.BuildConfigurationValue;
import com.google.devtools.build.lib.skyframe.BuildInfoCollectionFunction;
import com.google.devtools.build.lib.skyframe.BzlLoadFunction;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetKey;
import com.google.devtools.build.lib.skyframe.ManagedDirectoriesKnowledge;
import com.google.devtools.build.lib.skyframe.PackageFunction;
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.SkyFunctions;
import com.google.devtools.build.lib.skyframe.SkyframeExecutor;
import com.google.devtools.build.lib.skyframe.TargetPatternPhaseValue;
import com.google.devtools.build.lib.testutil.BlazeTestUtils;
import com.google.devtools.build.lib.testutil.FoundationTestCase;
import com.google.devtools.build.lib.testutil.SkyframeExecutorTestHelper;
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.skyframe.ErrorInfo;
import com.google.devtools.build.skyframe.InMemoryMemoizingEvaluator;
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.NoSuchElementException;
import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
import java.util.UUID;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import net.starlark.java.eval.StarlarkSemantics;
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 PackageOptions packageOptions;
  private BuildLanguageOptions buildLanguageOptions;
  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");
    mockToolsConfig.create(
        "bazel_tools_workspace/tools/jdk/local_java_repository.bzl",
        "def local_java_repository(**kwargs):",
        "  pass");
    initializeMockClient();

    packageOptions = parsePackageOptions();
    buildLanguageOptions = parseBuildLanguageOptions();
    workspaceStatusActionFactory = new AnalysisTestUtil.DummyWorkspaceStatusActionFactory();
    mutableActionGraph = new MapBasedActionGraph(actionKeyContext);
    ruleClassProvider = createRuleClassProvider();
    getOutputPath().createDirectoryAndParents();
    ImmutableList<PrecomputedValue.Injected> extraPrecomputedValues =
        ImmutableList.of(
            PrecomputedValue.injected(
                PrecomputedValue.STARLARK_SEMANTICS, StarlarkSemantics.DEFAULT),
            PrecomputedValue.injected(PrecomputedValue.REPO_ENV, ImmutableMap.of()),
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.REPOSITORY_OVERRIDES, ImmutableMap.of()),
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.RESOLVED_FILE_INSTEAD_OF_WORKSPACE, Optional.empty()),
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.DEPENDENCY_FOR_UNCONDITIONAL_FETCHING,
                RepositoryDelegatorFunction.DONT_FETCH_UNCONDITIONALLY),
            PrecomputedValue.injected(
                BuildInfoCollectionFunction.BUILD_INFO_FACTORIES,
                ruleClassProvider.getBuildInfoFactoriesAsMap()));
    PackageFactory.BuilderForTesting pkgFactoryBuilder =
        analysisMock
            .getPackageFactoryBuilderForTesting(directories)
            .setExtraPrecomputeValues(extraPrecomputedValues)
            .setEnvironmentExtensions(getEnvironmentExtensions())
            .setPackageValidator(getPackageValidator());
    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();
    if (usesInliningBzlLoadFunction()) {
      injectInliningBzlLoadFunction(skyframeExecutor, pkgFactory, directories);
    }
    SkyframeExecutorTestHelper.process(skyframeExecutor);
    skyframeExecutor.injectExtraPrecomputedValues(extraPrecomputedValues);
    packageOptions.defaultVisibility = ConstantRuleVisibility.PUBLIC;
    packageOptions.showLoadingProgress = true;
    packageOptions.globbingThreads = 7;
    skyframeExecutor.preparePackageLoading(
        new PathPackageLocator(
            outputBase,
            ImmutableList.of(root),
            BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY),
        packageOptions,
        buildLanguageOptions,
        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()));
  }

  private static void injectInliningBzlLoadFunction(
      SkyframeExecutor skyframeExecutor,
      PackageFactory packageFactory,
      BlazeDirectories directories) {
    ImmutableMap<SkyFunctionName, ? extends SkyFunction> skyFunctions =
        ((InMemoryMemoizingEvaluator) skyframeExecutor.getEvaluatorForTesting())
            .getSkyFunctionsForTesting();
    BzlLoadFunction bzlLoadFunction =
        BzlLoadFunction.createForInlining(
            packageFactory,
            directories,
            // Use a cache size of 2 for testing to balance coverage for where loads are present and
            // aren't present in the cache.
            /*bzlLoadValueCacheSize=*/ 2);
    bzlLoadFunction.resetInliningCache();
    // This doesn't override the BZL_LOAD -> BzlLoadFunction mapping, but nothing besides
    // PackageFunction should be requesting that key while using the inlining code path.
    ((PackageFunction) skyFunctions.get(SkyFunctions.PACKAGE))
        .setBzlLoadFunctionForInliningForTesting(bzlLoadFunction);
  }

  /**
   * Returns whether or not to use the inlined version of BzlLoadFunction in this test.
   *
   * @see BzlLoadFunction#computeInline
   */
  protected boolean usesInliningBzlLoadFunction() {
    return false;
  }

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

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

  /**
   * Called to create the rule class provider used in this test.
   *
   * <p>This function is called only once. (Multiple calls could lead to subtle identity bugs
   * between native objects.)
   */
  protected ConfiguredRuleClassProvider createRuleClassProvider() {
    return getAnalysisMock().createRuleClassProvider();
  }

  protected final ConfiguredRuleClassProvider getRuleClassProvider() {
    return ruleClassProvider;
  }

  protected ManagedDirectoriesKnowledge getManagedDirectoriesKnowledge() {
    return null;
  }

  protected final PackageFactory getPackageFactory() {
    return pkgFactory;
  }

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

  protected StarlarkSemantics getStarlarkSemantics() {
    return buildLanguageOptions.toStarlarkSemantics();
  }

  protected PackageValidator getPackageValidator() {
    return PackageValidator.NOOP_VALIDATOR;
  }

  protected final BuildConfigurationCollection createConfigurations(
      ImmutableMap<String, Object> starlarkOptions, 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");
    // 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(starlarkOptions);

    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,
            packageOptions.packagePath,
            reporter,
            rootDirectory,
            rootDirectory,
            BazelSkyframeExecutorConstants.BUILD_FILES_BY_PRIORITY);
    packageOptions.showLoadingProgress = true;
    packageOptions.globbingThreads = 7;
    skyframeExecutor.preparePackageLoading(
        pkgLocator,
        packageOptions,
        buildLanguageOptions,
        UUID.randomUUID(),
        ImmutableMap.of(),
        tsgm);
    skyframeExecutor.setActionEnv(ImmutableMap.of());
    skyframeExecutor.setDeletedPackages(ImmutableSet.copyOf(packageOptions.getDeletedPackages()));
    skyframeExecutor.injectExtraPrecomputedValues(
        ImmutableList.of(
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.RESOLVED_FILE_INSTEAD_OF_WORKSPACE, Optional.empty()),
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.OUTPUT_VERIFICATION_REPOSITORY_RULES,
                ImmutableSet.of()),
            PrecomputedValue.injected(
                RepositoryDelegatorFunction.RESOLVED_FILE_FOR_VERIFICATION, Optional.empty())));
  }

  protected void setPackageOptions(String... options) throws Exception {
    packageOptions = parsePackageOptions(options);
    setUpSkyframe();
  }

  protected void setBuildLanguageOptions(String... options) throws Exception {
    buildLanguageOptions = parseBuildLanguageOptions(options);
    setUpSkyframe();
  }

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

  private static BuildLanguageOptions parseBuildLanguageOptions(String... options)
      throws Exception {
    OptionsParser parser =
        OptionsParser.builder().optionsClasses(BuildLanguageOptions.class).build();
    parser.parse(options);
    return parser.getOptions(BuildLanguageOptions.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.
   *
   * <p>TODO(juliexxia): when Starlark option parsing exists, find a way to combine these parameters
   * into a single parameter so Starlark/native options don't have to be specified separately.
   *
   * @param starlarkOptions map of Starlark-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> starlarkOptions, 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(starlarkOptions, 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 ActionLookupKey() {
          @Nullable
          @Override
          public Label getLabel() {
            return null;
          }

          @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 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 Starlark tests that is equivalent to the one that
   * was used to create the given configured target.
   */
  protected RuleContext getRuleContextForStarlark(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, InterruptedException {
    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, InterruptedException {
    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, InterruptedException, 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
  protected 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 static Artifact findArtifactNamed(
      String name, NestedSet<Artifact> artifacts, Object context) {
    return artifacts.toList().stream()
        .filter(artifactNamed(name))
        .findFirst()
        .orElseThrow(
            () ->
                new NoSuchElementException(
                    String.format(
                        "Artifact named '%s' not found in %s (%s)", name, context, artifacts)));
  }

  private Action getGeneratingAction(
      String outputName, NestedSet<Artifact> filesToBuild, String providerName) {
    return getGeneratingAction(findArtifactNamed(outputName, filesToBuild, providerName));
  }

  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(
        findArtifactNamed(outputName, getFilesToBuild(target), target.getLabel()));
  }

  protected final List<String> getGeneratingSpawnActionArgs(Artifact artifact)
      throws CommandLineExpansionException, InterruptedException {
    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.
   *
   * <p>May return null on error; see {@link #getConfiguredTarget(Label, BuildConfiguration)}.
   */
  @Nullable
  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.
   *
   * <p>May return null on error; see {@link #getConfiguredTarget(Label, BuildConfiguration)}.
   */
  @Nullable
  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
   */
  // TODO(bazel-team): Should we work around b/26382502 by asserting here that the result is not
  // null?
  @Nullable
  protected ConfiguredTarget getConfiguredTarget(Label label, BuildConfiguration config) {
    try {
      return view.getConfiguredTargetForTesting(
          reporter, BlazeTestUtils.convertLabel(label), config);
    } catch (InvalidConfigurationException
        | StarlarkTransition.TransitionException
        | InterruptedException 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,
          InterruptedException {
    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, InterruptedException {
    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 Starlark 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 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) {
    ActionLookupKey actionLookupKey =
        ConfiguredTargetKey.builder()
            .setConfiguredTarget(owner)
            .setConfigurationKey(owner.getConfigurationKey())
            .build();
    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.builder()
            .setConfiguredTarget(owner)
            .setConfiguration(
                skyframeExecutor.getConfiguration(reporter, owner.getConfigurationKey()))
            .build());
  }

  /**
   * 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),
        (AspectKey)
            AspectValueKey.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.builder().setLabel(makeLabel(owner)).setConfiguration(config).build(),
        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.builder()
            .setConfiguredTarget(owner)
            .setConfiguration(configuration)
            .build();
    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().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 AspectKey getOwnerForAspect(
      ConfiguredTarget owner, NativeAspectClass creatingAspectFactory, AspectParameters params) {
    return (AspectKey)
        AspectValueKey.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().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.builder()
            .setConfiguredTarget(owner)
            .setConfiguration(
                skyframeExecutor.getConfiguration(reporter, owner.getConfigurationKey()))
            .build());
  }

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

  protected String getRelativeOutputPath() {
    return directories.getRelativeOutputPath();
  }

  /**
   * 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(), 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.builder()
        .setLabel(makeLabel(label))
        .setConfiguration(getConfiguration(label))
        .build();
  }

  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(
                new BuildOptionsView(fromConfig.getOptions(), transition.requiresOptionFragments()),
                eventCollector));
      } 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
        | InterruptedException 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(),
        /*explicitTargetPatterns=*/ ImmutableSet.of(),
        aspects,
        viewOptions,
        keepGoing,
        loadingPhaseThreads,
        AnalysisTestUtil.TOP_LEVEL_ARTIFACT_CONTEXT,
        reporter,
        eventBus);
  }

  protected static Predicate<Artifact> artifactNamed(String name) {
    return artifact -> name.equals(artifact.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 Artifact getSourceArtifactForNinjaBuild(PathFragment execPath, Root 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 getStarlarkSemantics() {
      return buildLanguageOptions.toStarlarkSemantics();
    }

    @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 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.STARLARK_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(RepositoryName.MAIN),
                convertLabelToPath(targetLabel)));

    return (PseudoAction<?>) pseudoAction;
  }

  /**
   * Converts the given label to an output path where double slashes and colons are replaced with
   * single slashes.
   */
  private static 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,
          /*rewindingEnabled=*/ false,
          LostInputsCheck.NONE,
          actionLogBufferPathGenerator.generate(ArtifactPathResolver.IDENTITY),
          reporter,
          clientEnv,
          /*topLevelFilesets=*/ ImmutableMap.of(),
          artifactExpander,
          /*actionFileSystem=*/ null,
          /*skyframeDepsResult*/ null,
          NestedSetExpander.DEFAULT);
    }
  }
}
