| // 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; | |
| import static com.google.common.truth.Truth.assertThat; | |
| import static com.google.devtools.build.lib.analysis.testing.ResolvedToolchainContextSubject.assertThat; | |
| import static org.junit.Assert.assertThrows; | |
| import com.google.common.collect.ImmutableList; | |
| import com.google.common.collect.ImmutableMap; | |
| import com.google.common.collect.ImmutableSet; | |
| import com.google.common.collect.ImmutableSetMultimap; | |
| import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement; | |
| import com.google.devtools.build.lib.analysis.platform.ToolchainTypeInfo; | |
| import com.google.devtools.build.lib.cmdline.Label; | |
| import com.google.devtools.build.lib.rules.platform.ToolchainTestCase; | |
| import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData; | |
| import com.google.devtools.build.lib.skyframe.ToolchainContextKey; | |
| import com.google.devtools.build.lib.skyframe.ToolchainException; | |
| import com.google.devtools.build.lib.skyframe.UnloadedToolchainContext; | |
| import com.google.devtools.build.lib.skyframe.UnloadedToolchainContextImpl; | |
| import org.junit.Test; | |
| import org.junit.runner.RunWith; | |
| import org.junit.runners.JUnit4; | |
| /** Tests for {@link ResolvedToolchainContext}. */ | |
| @RunWith(JUnit4.class) | |
| public class ResolvedToolchainContextTest extends ToolchainTestCase { | |
| @Test | |
| public void load() throws Exception { | |
| addToolchain( | |
| "extra", | |
| "extra_toolchain_linux", | |
| ImmutableList.of("//constraints:linux"), | |
| ImmutableList.of("//constraints:linux"), | |
| "baz"); | |
| ToolchainContextKey toolchainContextKey = | |
| ToolchainContextKey.key() | |
| .configurationKey(targetConfigKey) | |
| .toolchainTypes(testToolchainType) | |
| .build(); | |
| // Create a static UnloadedToolchainContext. | |
| UnloadedToolchainContext unloadedToolchainContext = | |
| UnloadedToolchainContextImpl.builder(toolchainContextKey) | |
| .setExecutionPlatform(linuxPlatform) | |
| .setTargetPlatform(linuxPlatform) | |
| .setToolchainTypes(ImmutableSet.of(testToolchainType)) | |
| .setRequestedLabelToToolchainType( | |
| ImmutableMap.of(testToolchainTypeLabel, testToolchainTypeInfo)) | |
| .setToolchainTypeToResolved( | |
| ImmutableSetMultimap.<ToolchainTypeInfo, Label>builder() | |
| .put( | |
| testToolchainTypeInfo, | |
| Label.parseAbsoluteUnchecked("//extra:extra_toolchain_linux_impl")) | |
| .build()) | |
| .build(); | |
| // Create the prerequisites. | |
| ConfiguredTargetAndData toolchain = | |
| getConfiguredTargetAndData( | |
| Label.parseAbsoluteUnchecked("//extra:extra_toolchain_linux_impl"), targetConfig); | |
| // Resolve toolchains. | |
| ResolvedToolchainContext toolchainContext = | |
| ResolvedToolchainContext.load( | |
| unloadedToolchainContext, | |
| "test", | |
| ImmutableList.of(toolchain)); | |
| assertThat(toolchainContext).isNotNull(); | |
| assertThat(toolchainContext).hasToolchainType(testToolchainTypeLabel); | |
| assertThat(toolchainContext) | |
| .forToolchainType(testToolchainTypeLabel) | |
| .getValue("data") | |
| .isEqualTo("baz"); | |
| } | |
| @Test | |
| public void load_mandatory_missing() throws Exception { | |
| ToolchainContextKey toolchainContextKey = | |
| ToolchainContextKey.key() | |
| .configurationKey(targetConfigKey) | |
| .toolchainTypes(testToolchainType) | |
| .build(); | |
| // Create a static UnloadedToolchainContext. | |
| UnloadedToolchainContext unloadedToolchainContext = | |
| UnloadedToolchainContextImpl.builder(toolchainContextKey) | |
| .setExecutionPlatform(linuxPlatform) | |
| .setTargetPlatform(linuxPlatform) | |
| .setToolchainTypes(ImmutableSet.of(testToolchainType)) | |
| .setRequestedLabelToToolchainType( | |
| ImmutableMap.of(testToolchainTypeLabel, testToolchainTypeInfo)) | |
| .build(); | |
| // Resolve toolchains. | |
| assertThrows( | |
| ToolchainException.class, | |
| () -> ResolvedToolchainContext.load(unloadedToolchainContext, "test", ImmutableList.of())); | |
| } | |
| @Test | |
| public void load_optional_present() throws Exception { | |
| addOptionalToolchain( | |
| "extra", | |
| "extra_toolchain_linux", | |
| ImmutableList.of("//constraints:linux"), | |
| ImmutableList.of("//constraints:linux"), | |
| "baz"); | |
| ToolchainContextKey toolchainContextKey = | |
| ToolchainContextKey.key() | |
| .configurationKey(targetConfigKey) | |
| .toolchainTypes(optionalToolchainType) | |
| .build(); | |
| // Create a static UnloadedToolchainContext. | |
| UnloadedToolchainContext unloadedToolchainContext = | |
| UnloadedToolchainContextImpl.builder(toolchainContextKey) | |
| .setExecutionPlatform(linuxPlatform) | |
| .setTargetPlatform(linuxPlatform) | |
| .setToolchainTypes(ImmutableSet.of(optionalToolchainType)) | |
| .setRequestedLabelToToolchainType( | |
| ImmutableMap.of(optionalToolchainTypeLabel, optionalToolchainTypeInfo)) | |
| .setToolchainTypeToResolved( | |
| ImmutableSetMultimap.<ToolchainTypeInfo, Label>builder() | |
| .put( | |
| optionalToolchainTypeInfo, | |
| Label.parseAbsoluteUnchecked("//extra:extra_toolchain_linux_impl")) | |
| .build()) | |
| .build(); | |
| // Create the prerequisites. | |
| ConfiguredTargetAndData toolchain = | |
| getConfiguredTargetAndData( | |
| Label.parseAbsoluteUnchecked("//extra:extra_toolchain_linux_impl"), targetConfig); | |
| // Resolve toolchains. | |
| ResolvedToolchainContext toolchainContext = | |
| ResolvedToolchainContext.load( | |
| unloadedToolchainContext, "test", ImmutableList.of(toolchain)); | |
| assertThat(toolchainContext).isNotNull(); | |
| assertThat(toolchainContext).hasToolchainType(optionalToolchainTypeLabel); | |
| assertThat(toolchainContext) | |
| .forToolchainType(optionalToolchainTypeLabel) | |
| .getValue("data") | |
| .isEqualTo("baz"); | |
| } | |
| @Test | |
| public void load_optional_missing() throws Exception { | |
| ToolchainContextKey toolchainContextKey = | |
| ToolchainContextKey.key() | |
| .configurationKey(targetConfigKey) | |
| .toolchainTypes(optionalToolchainType) | |
| .build(); | |
| // Create a static UnloadedToolchainContext. | |
| UnloadedToolchainContext unloadedToolchainContext = | |
| UnloadedToolchainContextImpl.builder(toolchainContextKey) | |
| .setExecutionPlatform(linuxPlatform) | |
| .setTargetPlatform(linuxPlatform) | |
| .setToolchainTypes(ImmutableSet.of(optionalToolchainType)) | |
| .setRequestedLabelToToolchainType( | |
| ImmutableMap.of(optionalToolchainTypeLabel, optionalToolchainTypeInfo)) | |
| .build(); | |
| // Resolve toolchains. | |
| ResolvedToolchainContext toolchainContext = | |
| ResolvedToolchainContext.load(unloadedToolchainContext, "test", ImmutableList.of()); | |
| assertThat(toolchainContext).isNotNull(); | |
| // Missing optional toolchain type requirement is present. | |
| assertThat(toolchainContext).hasToolchainType(optionalToolchainTypeLabel); | |
| // Missing optional toolchain implementation is null. | |
| assertThat(toolchainContext).forToolchainType(optionalToolchainTypeLabel).isNull(); | |
| } | |
| @Test | |
| public void load_mixed() throws Exception { | |
| addToolchain( | |
| "extra", | |
| "extra_toolchain_linux", | |
| ImmutableList.of("//constraints:linux"), | |
| ImmutableList.of("//constraints:linux"), | |
| "baz"); | |
| ToolchainContextKey toolchainContextKey = | |
| ToolchainContextKey.key() | |
| .configurationKey(targetConfigKey) | |
| .toolchainTypes(testToolchainType, optionalToolchainType) | |
| .build(); | |
| // Create a static UnloadedToolchainContext. | |
| UnloadedToolchainContext unloadedToolchainContext = | |
| UnloadedToolchainContextImpl.builder(toolchainContextKey) | |
| .setExecutionPlatform(linuxPlatform) | |
| .setTargetPlatform(linuxPlatform) | |
| .setToolchainTypes(ImmutableSet.of(testToolchainType, optionalToolchainType)) | |
| .setRequestedLabelToToolchainType( | |
| ImmutableMap.<Label, ToolchainTypeInfo>builder() | |
| .put(testToolchainTypeLabel, testToolchainTypeInfo) | |
| .put(optionalToolchainTypeLabel, optionalToolchainTypeInfo) | |
| .build()) | |
| .setToolchainTypeToResolved( | |
| ImmutableSetMultimap.<ToolchainTypeInfo, Label>builder() | |
| .put( | |
| testToolchainTypeInfo, | |
| Label.parseAbsoluteUnchecked("//extra:extra_toolchain_linux_impl")) | |
| .build()) | |
| .build(); | |
| // Create the prerequisites. | |
| ConfiguredTargetAndData testToolchain = | |
| getConfiguredTargetAndData( | |
| Label.parseAbsoluteUnchecked("//extra:extra_toolchain_linux_impl"), targetConfig); | |
| // Resolve toolchains. | |
| ResolvedToolchainContext toolchainContext = | |
| ResolvedToolchainContext.load( | |
| unloadedToolchainContext, "test", ImmutableList.of(testToolchain)); | |
| assertThat(toolchainContext).isNotNull(); | |
| // Test toolchain is present. | |
| assertThat(toolchainContext).hasToolchainType(testToolchainTypeLabel); | |
| assertThat(toolchainContext) | |
| .forToolchainType(testToolchainTypeLabel) | |
| .getValue("data") | |
| .isEqualTo("baz"); | |
| // Missing optional toolchain type requirement is present. | |
| assertThat(toolchainContext).hasToolchainType(optionalToolchainTypeLabel); | |
| // Missing optional toolchain implementation is null. | |
| assertThat(toolchainContext).forToolchainType(optionalToolchainTypeLabel).isNull(); | |
| } | |
| @Test | |
| public void load_aliasedToolchain() throws Exception { | |
| scratch.file( | |
| "alias/BUILD", "alias(name = 'toolchain', actual = '//extra:extra_toolchain_linux_impl')"); | |
| addToolchain( | |
| "extra", | |
| "extra_toolchain_linux", | |
| ImmutableList.of("//constraints:linux"), | |
| ImmutableList.of("//constraints:linux"), | |
| "baz"); | |
| ToolchainContextKey toolchainContextKey = | |
| ToolchainContextKey.key() | |
| .configurationKey(targetConfigKey) | |
| .toolchainTypes(testToolchainType) | |
| .build(); | |
| // Create a static UnloadedToolchainContext. | |
| UnloadedToolchainContext unloadedToolchainContext = | |
| UnloadedToolchainContextImpl.builder(toolchainContextKey) | |
| .setExecutionPlatform(linuxPlatform) | |
| .setTargetPlatform(linuxPlatform) | |
| .setToolchainTypes(ImmutableSet.of(testToolchainType)) | |
| .setRequestedLabelToToolchainType( | |
| ImmutableMap.of(testToolchainTypeLabel, testToolchainTypeInfo)) | |
| .setToolchainTypeToResolved( | |
| ImmutableSetMultimap.<ToolchainTypeInfo, Label>builder() | |
| .put(testToolchainTypeInfo, Label.parseAbsoluteUnchecked("//alias:toolchain")) | |
| .build()) | |
| .build(); | |
| // Create the prerequisites. | |
| ConfiguredTargetAndData toolchain = | |
| getConfiguredTargetAndData(Label.parseAbsoluteUnchecked("//alias:toolchain"), targetConfig); | |
| // Resolve toolchains. | |
| ResolvedToolchainContext toolchainContext = | |
| ResolvedToolchainContext.load( | |
| unloadedToolchainContext, | |
| "test", | |
| ImmutableList.of(toolchain)); | |
| assertThat(toolchainContext).isNotNull(); | |
| assertThat(toolchainContext).hasToolchainType(testToolchainTypeLabel); | |
| assertThat(toolchainContext) | |
| .forToolchainType(testToolchainTypeLabel) | |
| .getValue("data") | |
| .isEqualTo("baz"); | |
| } | |
| @Test | |
| public void load_notToolchain() throws Exception { | |
| scratch.file("foo/BUILD", "filegroup(name = 'not_a_toolchain')"); | |
| ToolchainContextKey toolchainContextKey = | |
| ToolchainContextKey.key() | |
| .configurationKey(targetConfigKey) | |
| .toolchainTypes(testToolchainType) | |
| .build(); | |
| // Create a static UnloadedToolchainContext. | |
| UnloadedToolchainContext unloadedToolchainContext = | |
| UnloadedToolchainContextImpl.builder(toolchainContextKey) | |
| .setExecutionPlatform(linuxPlatform) | |
| .setTargetPlatform(linuxPlatform) | |
| .setToolchainTypes(ImmutableSet.of(testToolchainType)) | |
| .setRequestedLabelToToolchainType( | |
| ImmutableMap.of(testToolchainTypeLabel, testToolchainTypeInfo)) | |
| .setToolchainTypeToResolved( | |
| ImmutableSetMultimap.<ToolchainTypeInfo, Label>builder() | |
| .put( | |
| testToolchainTypeInfo, | |
| Label.parseAbsoluteUnchecked("//foo:not_a_toolchain")) | |
| .build()) | |
| .build(); | |
| // Create the prerequisites, which is not actually a valid toolchain. | |
| ConfiguredTargetAndData toolchain = | |
| getConfiguredTargetAndData( | |
| Label.parseAbsoluteUnchecked("//foo:not_a_toolchain"), targetConfig); | |
| assertThrows( | |
| ToolchainException.class, | |
| () -> | |
| ResolvedToolchainContext.load( | |
| unloadedToolchainContext, | |
| "test", | |
| ImmutableList.of(toolchain))); | |
| } | |
| @Test | |
| public void load_withTemplateVariables() throws Exception { | |
| // Add new toolchain rule that provides template variables. | |
| Label variableToolchainTypeLabel = | |
| Label.parseAbsoluteUnchecked("//variable:variable_toolchain_type"); | |
| ToolchainTypeRequirement variableToolchainType = | |
| ToolchainTypeRequirement.create(variableToolchainTypeLabel); | |
| ToolchainTypeInfo variableToolchainTypeInfo = | |
| ToolchainTypeInfo.create(variableToolchainTypeLabel); | |
| scratch.file( | |
| "variable/variable_toolchain_def.bzl", | |
| "def _impl(ctx):", | |
| " value = ctx.attr.value", | |
| " toolchain = platform_common.ToolchainInfo()", | |
| " template_variables = platform_common.TemplateVariableInfo({'VALUE': value})", | |
| " return [toolchain, template_variables]", | |
| "variable_toolchain = rule(", | |
| " implementation = _impl,", | |
| " attrs = {'value': attr.string()})"); | |
| // Create instance of new toolchain and register it. | |
| scratch.file( | |
| "variable/BUILD", | |
| "load('//variable:variable_toolchain_def.bzl', 'variable_toolchain')", | |
| "toolchain_type(name = 'variable_toolchain_type')", | |
| "variable_toolchain(", | |
| " name='variable_toolchain_impl',", | |
| " value = 'foo')"); | |
| ToolchainContextKey toolchainContextKey = | |
| ToolchainContextKey.key() | |
| .configurationKey(targetConfigKey) | |
| .toolchainTypes(testToolchainType) | |
| .build(); | |
| // Create a static UnloadedToolchainContext. | |
| UnloadedToolchainContext unloadedToolchainContext = | |
| UnloadedToolchainContextImpl.builder(toolchainContextKey) | |
| .setExecutionPlatform(linuxPlatform) | |
| .setTargetPlatform(linuxPlatform) | |
| .setToolchainTypes(ImmutableSet.of(variableToolchainType)) | |
| .setRequestedLabelToToolchainType( | |
| ImmutableMap.of(variableToolchainTypeLabel, variableToolchainTypeInfo)) | |
| .setToolchainTypeToResolved( | |
| ImmutableSetMultimap.<ToolchainTypeInfo, Label>builder() | |
| .put( | |
| variableToolchainTypeInfo, | |
| Label.parseAbsoluteUnchecked("//variable:variable_toolchain_impl")) | |
| .build()) | |
| .build(); | |
| // Create the prerequisites. | |
| ConfiguredTargetAndData toolchain = | |
| getConfiguredTargetAndData( | |
| Label.parseAbsoluteUnchecked("//variable:variable_toolchain_impl"), targetConfig); | |
| ResolvedToolchainContext toolchainContext = | |
| ResolvedToolchainContext.load( | |
| unloadedToolchainContext, | |
| "test", | |
| ImmutableList.of(toolchain)); | |
| assertThat(toolchainContext).isNotNull(); | |
| assertThat(toolchainContext).hasToolchainType(variableToolchainTypeLabel); | |
| assertThat(toolchainContext.templateVariableProviders()).hasSize(1); | |
| assertThat(toolchainContext.templateVariableProviders().get(0).getVariables()) | |
| .containsExactly("VALUE", "foo"); | |
| } | |
| } |