Skip to content

Commit

Permalink
Add tests for ResolvedToolchainContext will missing optional toolchains.
Browse files Browse the repository at this point in the history
Part of Optional Toolchains (bazelbuild#14726).
  • Loading branch information
katre committed Apr 19, 2022
1 parent 2907d15 commit 2fec3fe
Show file tree
Hide file tree
Showing 2 changed files with 208 additions and 6 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 @@ -30,6 +30,7 @@
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.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
Expand All @@ -38,7 +39,17 @@
@RunWith(JUnit4.class)
public class ResolvedToolchainContextTest extends ToolchainTestCase {

// TODO(https://github.com/bazelbuild/bazel/issues/14726): Add tests for optional toolchain types.
Label optionalToolchainTypeLabel;
ToolchainTypeRequirement optionalToolchainType;
ToolchainTypeInfo optionalToolchainTypeInfo;

@Before
public void createOptionalToolchainType() {
optionalToolchainTypeLabel = Label.parseAbsoluteUnchecked("//toolchain:optional_toolchain");
optionalToolchainType =
ToolchainTypeRequirement.builder(optionalToolchainTypeLabel).mandatory(false).build();
optionalToolchainTypeInfo = ToolchainTypeInfo.create(optionalToolchainTypeLabel);
}

@Test
public void load() throws Exception {
Expand Down Expand Up @@ -90,6 +101,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 {
addToolchain(
"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

0 comments on commit 2fec3fe

Please sign in to comment.