blob: bbaa6c27e221fe8d23a767ada6acd86de2e6eb09 [file] [log] [blame]
// 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.toolchains.ToolchainContextKey;
import com.google.devtools.build.lib.skyframe.toolchains.ToolchainException;
import com.google.devtools.build.lib.skyframe.toolchains.UnloadedToolchainContext;
import com.google.devtools.build.lib.skyframe.toolchains.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.parseCanonicalUnchecked("//extra:extra_toolchain_linux_impl"))
.build())
.build();
// Create the prerequisites.
ConfiguredTargetAndData toolchain =
getConfiguredTargetAndData(
Label.parseCanonicalUnchecked("//extra:extra_toolchain_linux_impl"), targetConfig);
// Resolve toolchains.
ResolvedToolchainContext toolchainContext =
ResolvedToolchainContext.load(unloadedToolchainContext, "test", ImmutableSet.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", ImmutableSet.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.parseCanonicalUnchecked("//extra:extra_toolchain_linux_impl"))
.build())
.build();
// Create the prerequisites.
ConfiguredTargetAndData toolchain =
getConfiguredTargetAndData(
Label.parseCanonicalUnchecked("//extra:extra_toolchain_linux_impl"), targetConfig);
// Resolve toolchains.
ResolvedToolchainContext toolchainContext =
ResolvedToolchainContext.load(unloadedToolchainContext, "test", ImmutableSet.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", ImmutableSet.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.parseCanonicalUnchecked("//extra:extra_toolchain_linux_impl"))
.build())
.build();
// Create the prerequisites.
ConfiguredTargetAndData testToolchain =
getConfiguredTargetAndData(
Label.parseCanonicalUnchecked("//extra:extra_toolchain_linux_impl"), targetConfig);
// Resolve toolchains.
ResolvedToolchainContext toolchainContext =
ResolvedToolchainContext.load(
unloadedToolchainContext, "test", ImmutableSet.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.parseCanonicalUnchecked("//alias:toolchain"))
.build())
.build();
// Create the prerequisites.
ConfiguredTargetAndData toolchain =
getConfiguredTargetAndData(
Label.parseCanonicalUnchecked("//alias:toolchain"), targetConfig);
// Resolve toolchains.
ResolvedToolchainContext toolchainContext =
ResolvedToolchainContext.load(unloadedToolchainContext, "test", ImmutableSet.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.parseCanonicalUnchecked("//foo:not_a_toolchain"))
.build())
.build();
// Create the prerequisites, which is not actually a valid toolchain.
ConfiguredTargetAndData toolchain =
getConfiguredTargetAndData(
Label.parseCanonicalUnchecked("//foo:not_a_toolchain"), targetConfig);
assertThrows(
ToolchainException.class,
() ->
ResolvedToolchainContext.load(
unloadedToolchainContext, "test", ImmutableSet.of(toolchain)));
}
@Test
public void load_withTemplateVariables() throws Exception {
// Add new toolchain rule that provides template variables.
Label variableToolchainTypeLabel =
Label.parseCanonicalUnchecked("//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.parseCanonicalUnchecked("//variable:variable_toolchain_impl"))
.build())
.build();
// Create the prerequisites.
ConfiguredTargetAndData toolchain =
getConfiguredTargetAndData(
Label.parseCanonicalUnchecked("//variable:variable_toolchain_impl"), targetConfig);
ResolvedToolchainContext toolchainContext =
ResolvedToolchainContext.load(unloadedToolchainContext, "test", ImmutableSet.of(toolchain));
assertThat(toolchainContext).isNotNull();
assertThat(toolchainContext).hasToolchainType(variableToolchainTypeLabel);
assertThat(toolchainContext.templateVariableProviders()).hasSize(1);
assertThat(toolchainContext.templateVariableProviders().get(0).getVariables())
.containsExactly("VALUE", "foo");
}
}