| /* |
| * 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); |
| } |
| } |