// 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.devtools.build.lib.skyframe; import static com.google.common.truth.Truth.assertThat; import static com.google.devtools.build.skyframe.EvaluationResultSubjectFactory.assertThatEvaluationResult; import com.google.common.collect.ImmutableList; import com.google.common.testing.EqualsTester; import com.google.common.truth.DefaultSubject; import com.google.common.truth.Subject; import com.google.devtools.build.lib.analysis.platform.ConstraintSettingInfo; import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo; import com.google.devtools.build.lib.analysis.platform.DeclaredToolchainInfo; import com.google.devtools.build.lib.analysis.platform.PlatformInfo; import com.google.devtools.build.lib.cmdline.Label; import com.google.devtools.build.lib.rules.platform.ToolchainTestCase; import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils; import com.google.devtools.build.skyframe.EvaluationResult; import com.google.devtools.build.skyframe.SkyKey; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; /** Tests for {@link ToolchainResolutionValue} and {@link ToolchainResolutionFunction}. */ @RunWith(JUnit4.class) public class ToolchainResolutionFunctionTest extends ToolchainTestCase { private EvaluationResult invokeToolchainResolution(SkyKey key) throws InterruptedException { try { getSkyframeExecutor().getSkyframeBuildView().enableAnalysis(true); return SkyframeExecutorTestUtils.evaluate( getSkyframeExecutor(), key, /*keepGoing=*/ false, reporter); } finally { getSkyframeExecutor().getSkyframeBuildView().enableAnalysis(false); } } @Test public void testResolution() throws Exception { SkyKey key = ToolchainResolutionValue.key(targetConfig, testToolchainType, linuxPlatform, macPlatform); EvaluationResult result = invokeToolchainResolution(key); assertThatEvaluationResult(result).hasNoError(); ToolchainResolutionValue toolchainResolutionValue = result.get(key); assertThat(toolchainResolutionValue.toolchainLabel()) .isEqualTo(makeLabel("//toolchain:test_toolchain_2")); } @Test public void testResolution_flagOverride() throws Exception { // Add extra toolchain. scratch.file( "extra/BUILD", "load('//toolchain:toolchain_def.bzl', 'test_toolchain')", "test_toolchain(", " name='extra_toolchain_impl',", " data = 'extra')"); useConfiguration( "--toolchain_resolution_override=" + testToolchainType + "=//extra:extra_toolchain_impl"); SkyKey key = ToolchainResolutionValue.key(targetConfig, testToolchainType, linuxPlatform, macPlatform); EvaluationResult result = invokeToolchainResolution(key); assertThatEvaluationResult(result).hasNoError(); ToolchainResolutionValue toolchainResolutionValue = result.get(key); assertThat(toolchainResolutionValue.toolchainLabel()) .isEqualTo(makeLabel("//extra:extra_toolchain_impl")); } @Test public void testResolution_noneFound() throws Exception { // Clear the toolchains. rewriteWorkspace(); SkyKey key = ToolchainResolutionValue.key(targetConfig, testToolchainType, linuxPlatform, macPlatform); EvaluationResult result = invokeToolchainResolution(key); assertThatEvaluationResult(result) .hasErrorEntryForKeyThat(key) .hasExceptionThat() .hasMessageThat() .contains("no matching toolchain found for //toolchain:test_toolchain"); } @Test public void testResolveConstraints() throws Exception { ConstraintSettingInfo setting1 = ConstraintSettingInfo.create(makeLabel("//constraint:setting1")); ConstraintSettingInfo setting2 = ConstraintSettingInfo.create(makeLabel("//constraint:setting2")); ConstraintValueInfo constraint1a = ConstraintValueInfo.create(setting1, makeLabel("//constraint:value1a")); ConstraintValueInfo constraint1b = ConstraintValueInfo.create(setting1, makeLabel("//constraint:value1b")); ConstraintValueInfo constraint2a = ConstraintValueInfo.create(setting2, makeLabel("//constraint:value2a")); ConstraintValueInfo constraint2b = ConstraintValueInfo.create(setting2, makeLabel("//constraint:value2b")); Label toolchainType1 = makeLabel("//toolchain:type1"); Label toolchainType2 = makeLabel("//toolchain:type2"); DeclaredToolchainInfo toolchain1a = DeclaredToolchainInfo.create( toolchainType1, ImmutableList.of(constraint1a, constraint2a), ImmutableList.of(constraint1a, constraint2a), makeLabel("//toolchain:toolchain1a")); DeclaredToolchainInfo toolchain1b = DeclaredToolchainInfo.create( toolchainType1, ImmutableList.of(constraint1a, constraint2b), ImmutableList.of(constraint1a, constraint2b), makeLabel("//toolchain:toolchain1b")); DeclaredToolchainInfo toolchain2a = DeclaredToolchainInfo.create( toolchainType2, ImmutableList.of(constraint1b, constraint2a), ImmutableList.of(constraint1b, constraint2a), makeLabel("//toolchain:toolchain2a")); DeclaredToolchainInfo toolchain2b = DeclaredToolchainInfo.create( toolchainType2, ImmutableList.of(constraint1b, constraint2b), ImmutableList.of(constraint1b, constraint2b), makeLabel("//toolchain:toolchain2b")); ImmutableList allToolchains = ImmutableList.of(toolchain1a, toolchain1b, toolchain2a, toolchain2b); assertToolchainResolution( toolchainType1, ImmutableList.of(constraint1a, constraint2a), ImmutableList.of(constraint1a, constraint2a), allToolchains) .isEqualTo(toolchain1a); assertToolchainResolution( toolchainType1, ImmutableList.of(constraint1a, constraint2b), ImmutableList.of(constraint1a, constraint2b), allToolchains) .isEqualTo(toolchain1b); assertToolchainResolution( toolchainType2, ImmutableList.of(constraint1b, constraint2a), ImmutableList.of(constraint1b, constraint2a), allToolchains) .isEqualTo(toolchain2a); assertToolchainResolution( toolchainType2, ImmutableList.of(constraint1b, constraint2b), ImmutableList.of(constraint1b, constraint2b), allToolchains) .isEqualTo(toolchain2b); // No toolchains of type. assertToolchainResolution( makeLabel("//toolchain:type3"), ImmutableList.of(constraint1a, constraint2a), ImmutableList.of(constraint1a, constraint2a), allToolchains) .isNull(); } private Subject assertToolchainResolution( Label toolchainType, Iterable targetConstraints, Iterable execConstraints, ImmutableList toolchains) throws Exception { PlatformInfo execPlatform = PlatformInfo.builder() .setLabel(makeLabel("//platform:exec")) .addConstraints(execConstraints) .build(); PlatformInfo targetPlatform = PlatformInfo.builder() .setLabel(makeLabel("//platform:target")) .addConstraints(targetConstraints) .build(); DeclaredToolchainInfo resolvedToolchain = ToolchainResolutionFunction.resolveConstraints( toolchainType, execPlatform, targetPlatform, toolchains, null); return assertThat(resolvedToolchain); } @Test public void testToolchainResolutionValue_equalsAndHashCode() { new EqualsTester() .addEqualityGroup( ToolchainResolutionValue.create(makeLabel("//test:toolchain_impl_1")), ToolchainResolutionValue.create(makeLabel("//test:toolchain_impl_1"))) .addEqualityGroup( ToolchainResolutionValue.create(makeLabel("//test:toolchain_impl_2")), ToolchainResolutionValue.create(makeLabel("//test:toolchain_impl_2"))); } }