/*
 * Copyright 2017 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.idea.blaze.cpp;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.collect.ImmutableList;
import com.google.idea.blaze.base.BlazeTestCase;
import com.google.idea.blaze.base.async.executor.BlazeExecutor;
import com.google.idea.blaze.base.async.executor.MockBlazeExecutor;
import com.google.idea.blaze.base.bazel.BazelBuildSystemProvider;
import com.google.idea.blaze.base.bazel.BuildSystemProvider;
import com.google.idea.blaze.base.ideinfo.ArtifactLocation;
import com.google.idea.blaze.base.ideinfo.CIdeInfo;
import com.google.idea.blaze.base.ideinfo.CToolchainIdeInfo;
import com.google.idea.blaze.base.ideinfo.TargetIdeInfo;
import com.google.idea.blaze.base.ideinfo.TargetMap;
import com.google.idea.blaze.base.ideinfo.TargetMapBuilder;
import com.google.idea.blaze.base.io.VirtualFileSystemProvider;
import com.google.idea.blaze.base.model.BlazeProjectData;
import com.google.idea.blaze.base.model.MockBlazeProjectDataBuilder;
import com.google.idea.blaze.base.model.primitives.ExecutionRootPath;
import com.google.idea.blaze.base.model.primitives.Kind;
import com.google.idea.blaze.base.model.primitives.TargetExpression;
import com.google.idea.blaze.base.model.primitives.WorkspacePath;
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
import com.google.idea.blaze.base.projectview.ProjectView;
import com.google.idea.blaze.base.projectview.ProjectViewSet;
import com.google.idea.blaze.base.projectview.section.ListSection;
import com.google.idea.blaze.base.projectview.section.sections.DirectoryEntry;
import com.google.idea.blaze.base.projectview.section.sections.DirectorySection;
import com.google.idea.blaze.base.projectview.section.sections.TargetSection;
import com.google.idea.blaze.base.scope.BlazeContext;
import com.google.idea.blaze.base.scope.ErrorCollector;
import com.google.idea.blaze.base.scope.output.IssueOutput;
import com.google.idea.blaze.base.settings.BlazeImportSettings;
import com.google.idea.blaze.base.settings.BlazeImportSettingsManager;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.impl.ProgressManagerImpl;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.jetbrains.cidr.lang.OCLanguageKind;
import com.jetbrains.cidr.lang.workspace.OCResolveConfiguration;
import com.jetbrains.cidr.lang.workspace.OCResolveRootAndConfiguration;
import java.io.File;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Tests for {@link BlazeConfigurationResolver}. */
@RunWith(JUnit4.class)
public class BlazeConfigurationResolverTest extends BlazeTestCase {
  private final BlazeContext context = new BlazeContext();
  private final ErrorCollector errorCollector = new ErrorCollector();
  private final WorkspaceRoot workspaceRoot = new WorkspaceRoot(new File("/root"));

  private BlazeConfigurationResolver resolver;
  private BlazeConfigurationResolverResult resolverResult;
  private MockCompilerVersionChecker compilerVersionChecker;
  private LocalFileSystem mockFileSystem;

  @Override
  protected void initTest(Container applicationServices, Container projectServices) {
    super.initTest(applicationServices, projectServices);
    applicationServices.register(BlazeExecutor.class, new MockBlazeExecutor());
    compilerVersionChecker = new MockCompilerVersionChecker("1234");
    applicationServices.register(CompilerVersionChecker.class, compilerVersionChecker);
    applicationServices.register(ProgressManager.class, new ProgressManagerImpl());
    applicationServices.register(VirtualFileManager.class, mock(VirtualFileManager.class));
    mockFileSystem = mock(LocalFileSystem.class);
    applicationServices.register(
        VirtualFileSystemProvider.class, mock(VirtualFileSystemProvider.class));
    when(VirtualFileSystemProvider.getInstance().getSystem()).thenReturn(mockFileSystem);

    projectServices.register(BlazeImportSettingsManager.class, new BlazeImportSettingsManager());
    BuildSystemProvider buildSystemProvider = new BazelBuildSystemProvider();
    registerExtensionPoint(BuildSystemProvider.EP_NAME, BuildSystemProvider.class)
        .registerExtension(buildSystemProvider);
    BlazeImportSettingsManager.getInstance(getProject())
        .setImportSettings(
            new BlazeImportSettings("", "", "", "", buildSystemProvider.buildSystem()));

    context.addOutputSink(IssueOutput.class, errorCollector);

    resolver = new BlazeConfigurationResolver(project);
    resolverResult = BlazeConfigurationResolverResult.empty(project);
  }

  @Test
  public void testEmptyProject() {
    ProjectView projectView = projectView(directories(), targets());
    TargetMap targetMap = TargetMapBuilder.builder().build();
    assertThatResolving(projectView, targetMap).producesNoConfigurations();
  }

  @Test
  public void testTargetWithoutSources() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:library"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(createCcTarget("//foo/bar:library", Kind.CC_LIBRARY, ImmutableList.of()))
            .build();
    assertThatResolving(projectView, targetMap).producesNoConfigurations();
  }

  @Test
  public void testTargetWithGeneratedSources() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:library"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(gen("foo/bar/library.cc"))))
            .build();
    assertThatResolving(projectView, targetMap).producesNoConfigurations();
  }

  @Test
  public void testTargetWithMixedSources() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:binary"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary",
                    Kind.CC_BINARY,
                    ImmutableList.of(src("foo/bar/binary.cc"), gen("foo/bar/generated.cc"))))
            .build();
    assertThatResolving(projectView, targetMap).producesConfigurationsFor("//foo/bar:binary");
  }

  @Test
  public void testSingleSourceTarget() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:binary"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary", Kind.CC_BINARY, ImmutableList.of(src("foo/bar/binary.cc"))))
            .build();
    assertThatResolving(projectView, targetMap).producesConfigurationsFor("//foo/bar:binary");
  }

  @Test
  public void testSingleSourceTargetWithLibraryDependencies() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:binary"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                        "//foo/bar:binary",
                        Kind.CC_BINARY,
                        ImmutableList.of(src("foo/bar/binary.cc")))
                    .addDependency("//bar/baz:library")
                    .addDependency("//third_party:library"))
            .addTarget(
                createCcTarget(
                    "//bar/baz:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("bar/baz/library.cc"))))
            .addTarget(
                createCcTarget(
                    "//third_party:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("third_party/library.cc"))))
            .build();
    assertThatResolving(projectView, targetMap).producesConfigurationsFor("//foo/bar:binary");
  }

  @Test
  public void testSingleSourceTargetWithSourceDependencies() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:binary"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                        "//foo/bar:binary",
                        Kind.CC_BINARY,
                        ImmutableList.of(src("foo/bar/binary.cc")))
                    .addDependency("//foo/bar:library")
                    .addDependency("//third_party:library"))
            .addTarget(
                createCcTarget(
                    "//foo/bar:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("foo/bar/library.cc")),
                    ImmutableList.of("SOME_DEFINE=1")))
            .addTarget(
                createCcTarget(
                    "//third_party:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("third_party/library.cc"))))
            .build();
    assertThatResolving(projectView, targetMap)
        .producesConfigurationsFor("//foo/bar:binary", "//foo/bar:library");
  }

  @Test
  public void testComplexProject() {
    ProjectView projectView =
        projectView(
            directories("foo/bar", "foo/baz"),
            targets("//foo:test", "//foo/bar:binary", "//foo/baz:test"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget("//foo:test", Kind.CC_TEST, ImmutableList.of(src("foo/test.cc")))
                    .addDependency("//foo:library")
                    .addDependency("//foo/bar:library")
                    .addDependency("//third_party:library"))
            .addTarget(
                createCcTarget(
                    "//foo:library", Kind.CC_TEST, ImmutableList.of(src("foo/library.cc"))))
            .addTarget(
                createCcTarget(
                        "//foo/bar:binary",
                        Kind.CC_BINARY,
                        ImmutableList.of(src("foo/bar/binary.cc")),
                        ImmutableList.of("SOME_DEFINE=1"))
                    .addDependency("//foo/bar:library")
                    .addDependency("//foo/bar:empty")
                    .addDependency("//foo/bar:generated")
                    .addDependency("//foo/bar:mixed")
                    .addDependency("//third_party:library"))
            .addTarget(
                createCcTarget(
                    "//foo/bar:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("foo/bar/library.cc")),
                    ImmutableList.of("SOME_DEFINE=2")))
            .addTarget(createCcTarget("//foo/bar:empty", Kind.CC_LIBRARY, ImmutableList.of()))
            .addTarget(
                createCcTarget(
                    "//foo/bar:generated",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(gen("foo/bar/generated.cc"))))
            .addTarget(
                createCcTarget(
                    "//foo/bar:mixed",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("foo/bar/mixed_src.cc"), gen("foo/bar/mixed_gen.cc")),
                    ImmutableList.of("SOME_DEFINE=3")))
            .addTarget(
                createCcTarget(
                        "//foo/baz:test",
                        Kind.CC_TEST,
                        ImmutableList.of(src("foo/baz/test.cc")),
                        ImmutableList.of("SOME_DEFINE=4"))
                    .addDependency("//foo/baz:binary")
                    .addDependency("//foo/baz:library")
                    .addDependency("//foo/qux:library"))
            .addTarget(
                createCcTarget(
                    "//foo/baz:binary",
                    Kind.CC_BINARY,
                    ImmutableList.of(src("foo/baz/binary.cc")),
                    ImmutableList.of("SOME_DEFINE=5")))
            .addTarget(
                createCcTarget(
                    "//foo/baz:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("foo/baz/library.cc")),
                    ImmutableList.of("SOME_DEFINE=6")))
            .addTarget(
                createCcTarget(
                    "//foo/qux:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("foo/qux/library.cc"))))
            .addTarget(
                createCcTarget(
                    "//third_party:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("third_party/library.cc"))))
            .build();
    assertThatResolving(projectView, targetMap)
        .producesConfigurationsFor(
            "//foo/bar:binary",
            "//foo/bar:library",
            "//foo/bar:mixed",
            "//foo/baz:test",
            "//foo/baz:binary",
            "//foo/baz:library");
  }

  @Test
  public void firstResolve_testNotIncremental() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:binary"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary", Kind.CC_BINARY, ImmutableList.of(src("foo/bar/binary.cc"))))
            .build();
    ImmutableList<BlazeResolveConfiguration> noReusedConfigurations = ImmutableList.of();
    assertThatResolving(projectView, targetMap)
        .reusedConfigurations(noReusedConfigurations, "//foo/bar:binary");
  }

  @Test
  public void identicalTargets_testIncrementalUpdateFullReuse() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:binary"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary", Kind.CC_BINARY, ImmutableList.of(src("foo/bar/binary.cc"))))
            .build();

    assertThatResolving(projectView, targetMap).producesConfigurationsFor("//foo/bar:binary");
    Collection<BlazeResolveConfiguration> initialConfigurations =
        resolverResult.getAllConfigurations();

    assertThatResolving(projectView, targetMap).reusedConfigurations(initialConfigurations);
  }

  @Test
  public void newTarget_testIncrementalUpdatePartlyReused() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:*"));
    TargetMapBuilder targetMapBuilder =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary",
                    Kind.CC_BINARY,
                    ImmutableList.of(src("foo/bar/binary.cc"))));
    assertThatResolving(projectView, targetMapBuilder.build())
        .producesConfigurationsFor("//foo/bar:binary");
    Collection<BlazeResolveConfiguration> initialConfigurations =
        resolverResult.getAllConfigurations();

    targetMapBuilder.addTarget(
        createCcTarget(
            "//foo/bar:library",
            Kind.CC_LIBRARY,
            ImmutableList.of(src("foo/bar/library.cc")),
            ImmutableList.of("OTHER=1")));

    assertThatResolving(projectView, targetMapBuilder.build())
        .reusedConfigurations(initialConfigurations, "//foo/bar:library");
  }

  @Test
  public void afterQueryingConfiguration_newTarget_testIncrementalUpdatePartlyReused() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:*"));
    TargetMapBuilder targetMapBuilder =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary",
                    Kind.CC_BINARY,
                    ImmutableList.of(src("foo/bar/binary.cc"))));
    assertThatResolving(projectView, targetMapBuilder.build())
        .producesConfigurationsFor("//foo/bar:binary");
    Collection<BlazeResolveConfiguration> initialConfigurations =
        resolverResult.getAllConfigurations();

    // Make sure that if we *query* the configuration in some way, it doesn't affect its
    // compatibility / reusability. There may be caches attached to the configuration and those
    // should not be compared when checking equivalence.
    OCResolveConfiguration firstConfiguration = initialConfigurations.iterator().next();
    firstConfiguration.getLibraryHeadersRoots(
        new OCResolveRootAndConfiguration(firstConfiguration, OCLanguageKind.CPP));

    targetMapBuilder.addTarget(
        createCcTarget(
            "//foo/bar:library",
            Kind.CC_LIBRARY,
            ImmutableList.of(src("foo/bar/library.cc")),
            ImmutableList.of("OTHER=1")));

    assertThatResolving(projectView, targetMapBuilder.build())
        .reusedConfigurations(initialConfigurations, "//foo/bar:library");
  }

  @Test
  public void completelyDifferentTargetsSameProjectView_testIncrementalUpdateNoReuse() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:*"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary", Kind.CC_BINARY, ImmutableList.of(src("foo/bar/binary.cc"))))
            .build();
    ImmutableList<BlazeResolveConfiguration> noReusedConfigurations = ImmutableList.of();
    assertThatResolving(projectView, targetMap)
        .reusedConfigurations(noReusedConfigurations, "//foo/bar:binary");

    TargetMap targetMap2 =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("foo/bar/library.cc")),
                    ImmutableList.of("OTHER=1")))
            .build();
    assertThatResolving(projectView, targetMap2)
        .reusedConfigurations(noReusedConfigurations, "//foo/bar:library");
  }

  @Test
  public void completelyDifferentTargetsDifferentProjectView_testIncrementalUpdateNoReuse() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:binary"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary", Kind.CC_BINARY, ImmutableList.of(src("foo/bar/binary.cc"))))
            .build();
    ImmutableList<BlazeResolveConfiguration> noReusedConfigurations = ImmutableList.of();
    assertThatResolving(projectView, targetMap)
        .reusedConfigurations(noReusedConfigurations, "//foo/bar:binary");

    ProjectView projectView2 = projectView(directories("foo/zoo"), targets("//foo/zoo:library"));
    TargetMap targetMap2 =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/zoo:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("foo/zoo/library.cc")),
                    ImmutableList.of("OTHER=1")))
            .build();
    assertThatResolving(projectView2, targetMap2)
        .reusedConfigurations(noReusedConfigurations, "//foo/zoo:library");
  }

  @Test
  public void changeCompilerVersion_testIncrementalUpdateNoReuse() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:binary"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary", Kind.CC_BINARY, ImmutableList.of(src("foo/bar/binary.cc"))))
            .build();

    ImmutableList<BlazeResolveConfiguration> noReusedConfigurations = ImmutableList.of();
    assertThatResolving(projectView, targetMap)
        .reusedConfigurations(noReusedConfigurations, "//foo/bar:binary");

    compilerVersionChecker.setCompilerVersion("cc modified version");
    assertThatResolving(projectView, targetMap)
        .reusedConfigurations(noReusedConfigurations, "//foo/bar:binary");
  }

  @Test
  public void noChange_testIncrementalUpdateGetChangedFiles() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:binary"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary", Kind.CC_BINARY, ImmutableList.of(src("foo/bar/binary.cc"))))
            .build();
    assertThatResolving(projectView, targetMap).producesConfigurationsFor("//foo/bar:binary");

    assertThatResolving(projectView, targetMap).hasChangedRemovedFiles(ImmutableList.of(), false);
  }

  @Test
  public void addFiles_testIncrementalUpdateGetChangedFiles() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:*"));
    TargetMapBuilder targetMapBuilder =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary",
                    Kind.CC_BINARY,
                    ImmutableList.of(src("foo/bar/binary.cc"))));
    TargetMap targetMap = targetMapBuilder.build();
    createVirtualFile("/root/foo/bar/binary.cc");
    assertThatResolving(projectView, targetMap).producesConfigurationsFor("//foo/bar:binary");

    TargetMap targetMap2 =
        targetMapBuilder
            .addTarget(
                createCcTarget(
                    "//foo/bar:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("foo/bar/library.cc"))))
            .build();
    VirtualFile libraryCc = createVirtualFile("/root/foo/bar/library.cc");
    assertThatResolving(projectView, targetMap2)
        .hasChangedRemovedFiles(ImmutableList.of(libraryCc.getPath()), true);
  }

  @Test
  public void removeFiles_testIncrementalUpdateGetChangedFiles() {
    ProjectView projectView = projectView(directories("foo/bar"), targets("//foo/bar:*"));
    TargetMap targetMap =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary", Kind.CC_BINARY, ImmutableList.of(src("foo/bar/binary.cc"))))
            .addTarget(
                createCcTarget(
                    "//foo/bar:library",
                    Kind.CC_LIBRARY,
                    ImmutableList.of(src("foo/bar/library.cc")),
                    ImmutableList.of("SOME_DEFINE=1")))
            .build();
    createVirtualFile("/root/foo/bar/binary.cc");
    createVirtualFile("/root/foo/bar/library.cc");
    assertThatResolving(projectView, targetMap)
        .producesConfigurationsFor("//foo/bar:binary", "//foo/bar:library");

    TargetMap targetMap2 =
        TargetMapBuilder.builder()
            .addTarget(createCcToolchain())
            .addTarget(
                createCcTarget(
                    "//foo/bar:binary", Kind.CC_BINARY, ImmutableList.of(src("foo/bar/binary.cc"))))
            .build();
    assertThatResolving(projectView, targetMap2).hasChangedRemovedFiles(ImmutableList.of(), true);
  }

  private static ArtifactLocation src(String path) {
    return ArtifactLocation.builder().setRelativePath(path).setIsSource(true).build();
  }

  private static ArtifactLocation gen(String path) {
    return ArtifactLocation.builder().setRelativePath(path).setIsSource(false).build();
  }

  private static TargetIdeInfo.Builder createCcTarget(
      String label, Kind kind, ImmutableList<ArtifactLocation> sources) {
    return createCcTarget(label, kind, sources, ImmutableList.of());
  }

  private static TargetIdeInfo.Builder createCcTarget(
      String label,
      Kind kind,
      ImmutableList<ArtifactLocation> sources,
      ImmutableList<String> defines) {
    TargetIdeInfo.Builder targetInfo =
        TargetIdeInfo.builder().setLabel(label).setKind(kind).addDependency("//:toolchain");
    sources.forEach(targetInfo::addSource);
    return targetInfo.setCInfo(CIdeInfo.builder().addSources(sources).addLocalDefines(defines));
  }

  private static TargetIdeInfo.Builder createCcToolchain() {
    return TargetIdeInfo.builder()
        .setLabel("//:toolchain")
        .setKind(Kind.CC_TOOLCHAIN)
        .setCToolchainInfo(
            CToolchainIdeInfo.builder().setCppExecutable(new ExecutionRootPath("cc")));
  }

  private static ListSection<DirectoryEntry> directories(String... directories) {
    return ListSection.builder(DirectorySection.KEY)
        .addAll(
            Arrays.stream(directories)
                .map(directory -> DirectoryEntry.include(WorkspacePath.createIfValid(directory)))
                .collect(Collectors.toList()))
        .build();
  }

  private static ListSection<TargetExpression> targets(String... targets) {
    return ListSection.builder(TargetSection.KEY)
        .addAll(
            Arrays.stream(targets).map(TargetExpression::fromString).collect(Collectors.toList()))
        .build();
  }

  private static ProjectView projectView(
      ListSection<DirectoryEntry> directories, ListSection<TargetExpression> targets) {
    return ProjectView.builder().add(directories).add(targets).build();
  }

  private VirtualFile createVirtualFile(String path) {
    VirtualFile mockFile = mock(VirtualFile.class);
    when(mockFile.getPath()).thenReturn(path);
    when(mockFileSystem.findFileByIoFile(new File(path))).thenReturn(mockFile);
    return mockFile;
  }

  private Subject assertThatResolving(ProjectView projectView, TargetMap targetMap) {
    BlazeProjectData blazeProjectData =
        MockBlazeProjectDataBuilder.builder(workspaceRoot).setTargetMap(targetMap).build();
    resolverResult =
        resolver.update(
            context,
            workspaceRoot,
            ProjectViewSet.builder().add(projectView).build(),
            blazeProjectData,
            resolverResult);
    errorCollector.assertNoIssues();
    return new Subject() {
      @Override
      public void producesConfigurationsFor(String... expected) {
        List<String> targets =
            resolverResult
                .getAllConfigurations()
                .stream()
                .map(configuration -> configuration.getDisplayName(false))
                .collect(Collectors.toList());
        assertThat(targets).containsExactly((Object[]) expected);
      }

      @Override
      public void producesNoConfigurations() {
        assertThat(resolverResult.getAllConfigurations()).isEmpty();
      }

      @Override
      public void reusedConfigurations(
          Collection<BlazeResolveConfiguration> expectedReused, String... expectedNotReused) {
        Collection<BlazeResolveConfiguration> currentConfigurations =
            resolverResult.getAllConfigurations();
        assertContainsAllInIdentity(expectedReused, currentConfigurations);
        List<String> notReusedTargets =
            currentConfigurations
                .stream()
                .filter(
                    configuration ->
                        expectedReused
                            .stream()
                            .noneMatch(reusedConfig -> configuration == reusedConfig))
                .map(configuration -> configuration.getDisplayName(false))
                .collect(Collectors.toList());
        assertThat(notReusedTargets).containsExactly((Object[]) expectedNotReused);
      }

      @Override
      public void hasChangedRemovedFiles(
          ImmutableList<String> expectedChangedFiles, boolean expectedHasChanges) {
        BlazeConfigurationResolverDiff diff = resolverResult.getConfigurationDiff();
        assertThat(diff).isNotNull();
        List<String> changedFileNames =
            diff.getChangedFiles().stream().map(VirtualFile::getPath).collect(Collectors.toList());
        assertThat(changedFileNames).containsExactlyElementsIn(expectedChangedFiles);
        assertThat(diff.hasChanges()).isEqualTo(expectedHasChanges);
      }

      // In newer truth libraries, we could use:
      // assertThat(actual).comparingElementsUsing(IdentityCorrespondence).containsAllIn(expected)
      // but that isn't available in truth 0.30 from older plugin APIs.
      private <T> void assertContainsAllInIdentity(Collection<T> expected, Collection<T> actual) {
        for (T expectedItem : expected) {
          assertThat(actual.stream().anyMatch(actualItem -> actualItem == expectedItem)).isTrue();
        }
      }
    };
  }

  private interface Subject {
    void producesConfigurationsFor(String... expected);

    void producesNoConfigurations();

    void reusedConfigurations(Collection<BlazeResolveConfiguration> reused, String... notReused);

    void hasChangedRemovedFiles(
        ImmutableList<String> expectedChangedFiles, boolean hasRemovedFiles);
  }
}
