Implement toolchain resolution via constraint checks.

Part of #2219.

Change-Id: I5777e9b6cafbb7586cbbfb5b300344fd4417513d
PiperOrigin-RevId: 162359389
diff --git a/src/test/java/com/google/devtools/build/lib/rules/platform/ToolchainTestCase.java b/src/test/java/com/google/devtools/build/lib/rules/platform/ToolchainTestCase.java
index 5d170ba..3b9548d 100644
--- a/src/test/java/com/google/devtools/build/lib/rules/platform/ToolchainTestCase.java
+++ b/src/test/java/com/google/devtools/build/lib/rules/platform/ToolchainTestCase.java
@@ -24,8 +24,8 @@
 /** Utility methods for setting up platform and toolchain related tests. */
 public abstract class ToolchainTestCase extends SkylarkTestCase {
 
-  public PlatformInfo targetPlatform;
-  public PlatformInfo hostPlatform;
+  public PlatformInfo linuxPlatform;
+  public PlatformInfo macPlatform;
 
   public ConstraintSettingInfo setting;
   public ConstraintValueInfo linuxConstraint;
@@ -46,18 +46,22 @@
     setting = ConstraintSettingInfo.create(makeLabel("//constraint:os"));
     linuxConstraint = ConstraintValueInfo.create(setting, makeLabel("//constraint:linux"));
     macConstraint = ConstraintValueInfo.create(setting, makeLabel("//constraint:mac"));
-  }
 
-  @Before
-  public void createPlatforms() throws Exception {
-    targetPlatform =
-        PlatformInfo.builder().setLabel(makeLabel("//platforms:target_platform")).build();
-    hostPlatform = PlatformInfo.builder().setLabel(makeLabel("//platforms:host_platform")).build();
+    linuxPlatform =
+        PlatformInfo.builder()
+            .setLabel(makeLabel("//platforms:target_platform"))
+            .addConstraint(linuxConstraint)
+            .build();
+    macPlatform =
+        PlatformInfo.builder()
+            .setLabel(makeLabel("//platforms:host_platform"))
+            .addConstraint(macConstraint)
+            .build();
   }
 
   @Before
   public void createToolchains() throws Exception {
-    rewriteWorkspace("register_toolchains('//toolchain:toolchain_1',  '//toolchain:toolchain_2')");
+    rewriteWorkspace("register_toolchains('//toolchain:toolchain_1', '//toolchain:toolchain_2')");
 
     scratch.file(
         "toolchain/BUILD",
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/BUILD b/src/test/java/com/google/devtools/build/lib/skyframe/BUILD
index d68e4e8..fd6714e 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/BUILD
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/BUILD
@@ -73,7 +73,6 @@
         "//src/main/java/com/google/devtools/build/lib/analysis/platform",
         "//src/main/java/com/google/devtools/build/lib/cmdline",
         "//src/main/java/com/google/devtools/build/lib/rules/cpp",
-        "//src/main/java/com/google/devtools/build/lib/rules/platform",
         "//src/main/java/com/google/devtools/build/skyframe",
         "//src/main/java/com/google/devtools/build/skyframe:skyframe-objects",
         "//src/test/java/com/google/devtools/build/lib:actions_testutil",
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunctionTest.java
index 88bc501..214cc61 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunctionTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainResolutionFunctionTest.java
@@ -17,7 +17,15 @@
 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;
@@ -32,6 +40,7 @@
 
   private EvaluationResult<ToolchainResolutionValue> invokeToolchainResolution(SkyKey key)
       throws InterruptedException {
+
     try {
       getSkyframeExecutor().getSkyframeBuildView().enableAnalysis(true);
       return SkyframeExecutorTestUtils.evaluate(
@@ -41,19 +50,17 @@
     }
   }
 
-  // TODO(katre): Current toolchain resolution does not actually check the constraints, it just
-  // returns the first toolchain available.
   @Test
   public void testResolution() throws Exception {
     SkyKey key =
-        ToolchainResolutionValue.key(targetConfig, testToolchainType, targetPlatform, hostPlatform);
+        ToolchainResolutionValue.key(targetConfig, testToolchainType, linuxPlatform, macPlatform);
     EvaluationResult<ToolchainResolutionValue> result = invokeToolchainResolution(key);
 
     assertThatEvaluationResult(result).hasNoError();
 
     ToolchainResolutionValue toolchainResolutionValue = result.get(key);
     assertThat(toolchainResolutionValue.toolchainLabel())
-        .isEqualTo(makeLabel("//toolchain:test_toolchain_1"));
+        .isEqualTo(makeLabel("//toolchain:test_toolchain_2"));
   }
 
   @Test
@@ -62,7 +69,7 @@
     rewriteWorkspace();
 
     SkyKey key =
-        ToolchainResolutionValue.key(targetConfig, testToolchainType, targetPlatform, hostPlatform);
+        ToolchainResolutionValue.key(targetConfig, testToolchainType, linuxPlatform, macPlatform);
     EvaluationResult<ToolchainResolutionValue> result = invokeToolchainResolution(key);
 
     assertThatEvaluationResult(result)
@@ -73,6 +80,110 @@
   }
 
   @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<DeclaredToolchainInfo> 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<DefaultSubject, Object> assertToolchainResolution(
+      Label toolchainType,
+      Iterable<ConstraintValueInfo> targetConstraints,
+      Iterable<ConstraintValueInfo> execConstraints,
+      ImmutableList<DeclaredToolchainInfo> 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);
+    return assertThat(resolvedToolchain);
+  }
+
+  @Test
   public void testToolchainResolutionValue_equalsAndHashCode() {
     new EqualsTester()
         .addEqualityGroup(