Skip to content

Commit

Permalink
Add tests for ResolvedToolchainContext with missing optional toolchains.
Browse files Browse the repository at this point in the history
Part of Optional Toolchains (#14726).

Closes #15296.

PiperOrigin-RevId: 444281581
  • Loading branch information
katre authored and copybara-github committed Apr 25, 2022
1 parent e13958c commit fafcd5a
Show file tree
Hide file tree
Showing 3 changed files with 250 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.analysis.config.ToolchainTypeRequirement;
import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils;
import com.google.devtools.build.lib.analysis.platform.ToolchainInfo;
import com.google.devtools.build.lib.analysis.platform.ToolchainTypeInfo;
Expand Down Expand Up @@ -48,25 +49,26 @@ public static ResolvedToolchainContext load(
Iterable<ConfiguredTargetAndData> toolchainTargets)
throws ToolchainException {

ImmutableMap.Builder<ToolchainTypeInfo, ToolchainInfo> toolchains =
ImmutableMap.Builder<ToolchainTypeInfo, ToolchainInfo> toolchainsBuilder =
new ImmutableMap.Builder<>();
ImmutableList.Builder<TemplateVariableInfo> templateVariableProviders =
new ImmutableList.Builder<>();

for (ConfiguredTargetAndData target : toolchainTargets) {
// Aliases are in toolchainTypeToResolved by the original alias label, not via the final
// target's label.
Label discoveredLabel = target.getConfiguredTarget().getOriginalLabel();
ToolchainInfo toolchainInfo = PlatformProviderUtils.toolchain(target.getConfiguredTarget());

for (ToolchainTypeInfo toolchainType :
unloadedToolchainContext.toolchainTypeToResolved().inverse().get(discoveredLabel)) {
ToolchainInfo toolchainInfo = PlatformProviderUtils.toolchain(target.getConfiguredTarget());

// If the toolchainType hadn't been resolved to an actual target, resolution would have
// failed with an error much earlier. However, the target might still not be an actual
// toolchain.
if (toolchainType != null) {
if (toolchainInfo != null) {
toolchains.put(toolchainType, toolchainInfo);
toolchainsBuilder.put(toolchainType, toolchainInfo);
} else {
throw new TargetNotToolchainException(toolchainType, discoveredLabel);
}
Expand All @@ -81,6 +83,20 @@ public static ResolvedToolchainContext load(
}
}

// Verify that all mandatory toolchain type requirements are present.
ImmutableMap<ToolchainTypeInfo, ToolchainInfo> toolchains = toolchainsBuilder.buildOrThrow();
for (ToolchainTypeRequirement toolchainTypeRequirement :
unloadedToolchainContext.toolchainTypes()) {
if (toolchainTypeRequirement.mandatory()) {
Label toolchainTypeLabel = toolchainTypeRequirement.toolchainType();
ToolchainTypeInfo toolchainTypeInfo =
unloadedToolchainContext.requestedLabelToToolchainType().get(toolchainTypeLabel);
if (!toolchains.containsKey(toolchainTypeInfo)) {
throw new MissingToolchainTypeRequirementException(toolchainTypeRequirement);
}
}
}

return new AutoValue_ResolvedToolchainContext(
// super:
unloadedToolchainContext.key(),
Expand All @@ -91,7 +107,7 @@ public static ResolvedToolchainContext load(
// this:
targetDescription,
unloadedToolchainContext.requestedLabelToToolchainType(),
toolchains.buildOrThrow(),
toolchains,
templateVariableProviders.build());
}

Expand Down Expand Up @@ -125,7 +141,7 @@ public ToolchainInfo forToolchainType(ToolchainTypeInfo toolchainType) {
}

/**
* Exception used when a toolchain type is required but the resolved target does not have
* Exception used when a toolchain type is requested but the resolved target does not have
* ToolchainInfo.
*/
static final class TargetNotToolchainException extends ToolchainException {
Expand All @@ -143,4 +159,20 @@ protected Code getDetailedCode() {
return Code.MISSING_PROVIDER;
}
}

/** Exception used when a toolchain type is required but noimplementation was found. */
private static class MissingToolchainTypeRequirementException extends ToolchainException {

MissingToolchainTypeRequirementException(ToolchainTypeRequirement toolchainTypeRequirement) {
super(
String.format(
"toolchain type %s was mandatory but is not present",
toolchainTypeRequirement.toolchainType()));
}

@Override
protected Code getDetailedCode() {
return Code.NO_MATCHING_TOOLCHAIN;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@
@RunWith(JUnit4.class)
public class ResolvedToolchainContextTest extends ToolchainTestCase {

// TODO(https://github.com/bazelbuild/bazel/issues/14726): Add tests for optional toolchain types.

@Test
public void load() throws Exception {
addToolchain(
Expand Down Expand Up @@ -90,6 +88,165 @@ public void load() throws Exception {
.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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ public abstract class ToolchainTestCase extends BuildViewTestCase {
public ToolchainTypeRequirement testToolchainType;
public ToolchainTypeInfo testToolchainTypeInfo;

public Label optionalToolchainTypeLabel;
public ToolchainTypeRequirement optionalToolchainType;
public ToolchainTypeInfo optionalToolchainTypeInfo;

protected static IterableSubject assertToolchainLabels(
RegisteredToolchainsValue registeredToolchainsValue) {
return assertToolchainLabels(registeredToolchainsValue, null);
Expand Down Expand Up @@ -149,6 +153,7 @@ public void createConstraints() throws Exception {
public void addToolchain(
String packageName,
String toolchainName,
Label toolchainType,
Collection<String> execConstraints,
Collection<String> targetConstraints,
String data)
Expand All @@ -158,7 +163,7 @@ public void addToolchain(
"load('//toolchain:toolchain_def.bzl', 'test_toolchain')",
"toolchain(",
" name = '" + toolchainName + "',",
" toolchain_type = '//toolchain:test_toolchain',",
" toolchain_type = '" + toolchainType + "',",
" exec_compatible_with = [" + formatConstraints(execConstraints) + "],",
" target_compatible_with = [" + formatConstraints(targetConstraints) + "],",
" toolchain = ':" + toolchainName + "_impl')",
Expand All @@ -167,6 +172,40 @@ public void addToolchain(
" data = '" + data + "')");
}

public void addToolchain(
String packageName,
String toolchainName,
Collection<String> execConstraints,
Collection<String> targetConstraints,
String data)
throws Exception {

addToolchain(
packageName,
toolchainName,
testToolchainTypeLabel,
execConstraints,
targetConstraints,
data);
}

public void addOptionalToolchain(
String packageName,
String toolchainName,
Collection<String> execConstraints,
Collection<String> targetConstraints,
String data)
throws Exception {

addToolchain(
packageName,
toolchainName,
optionalToolchainTypeLabel,
execConstraints,
targetConstraints,
data);
}

@Before
public void createToolchains() throws Exception {
rewriteWorkspace("register_toolchains('//toolchain:toolchain_1', '//toolchain:toolchain_2')");
Expand All @@ -182,7 +221,20 @@ public void createToolchains() throws Exception {
" attrs = {",
" 'data': attr.string()})");

scratch.file("toolchain/BUILD", "toolchain_type(name = 'test_toolchain')");
scratch.file(
"toolchain/BUILD",
"toolchain_type(name = 'test_toolchain')",
"toolchain_type(name = 'optional_toolchain')");

testToolchainTypeLabel = Label.parseAbsoluteUnchecked("//toolchain:test_toolchain");
testToolchainType = ToolchainTypeRequirement.create(testToolchainTypeLabel);
testToolchainTypeInfo = ToolchainTypeInfo.create(testToolchainTypeLabel);

optionalToolchainTypeLabel = Label.parseAbsoluteUnchecked("//toolchain:optional_toolchain");
optionalToolchainType =
ToolchainTypeRequirement.builder(optionalToolchainTypeLabel).mandatory(false).build();
optionalToolchainTypeInfo = ToolchainTypeInfo.create(optionalToolchainTypeLabel);

addToolchain(
"toolchain",
"toolchain_1",
Expand All @@ -195,10 +247,6 @@ public void createToolchains() throws Exception {
ImmutableList.of("//constraints:mac"),
ImmutableList.of("//constraints:linux"),
"bar");

testToolchainTypeLabel = Label.parseAbsoluteUnchecked("//toolchain:test_toolchain");
testToolchainType = ToolchainTypeRequirement.create(testToolchainTypeLabel);
testToolchainTypeInfo = ToolchainTypeInfo.create(testToolchainTypeLabel);
}

protected EvaluationResult<RegisteredToolchainsValue> requestToolchainsFromSkyframe(
Expand Down

0 comments on commit fafcd5a

Please sign in to comment.