Rename ToolchainResolutionFunction to SingleToolchainResolutionFunction.

Part of work on execution transitions, #7935.

Closes #8065.

PiperOrigin-RevId: 243843398
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/SingleToolchainResolutionFunctionTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/SingleToolchainResolutionFunctionTest.java
new file mode 100644
index 0000000..e12bb7e
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/SingleToolchainResolutionFunctionTest.java
@@ -0,0 +1,276 @@
+// 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.ImmutableCollection;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.testing.EqualsTester;
+import com.google.devtools.build.lib.actions.Actions.GeneratingActions;
+import com.google.devtools.build.lib.actions.util.InjectedActionLookupKey;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.TransitiveInfoProvider;
+import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
+import com.google.devtools.build.lib.collect.nestedset.Order;
+import com.google.devtools.build.lib.events.Location;
+import com.google.devtools.build.lib.packages.InfoInterface;
+import com.google.devtools.build.lib.packages.NativeProvider;
+import com.google.devtools.build.lib.packages.Provider;
+import com.google.devtools.build.lib.rules.platform.ToolchainTestCase;
+import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
+import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
+import com.google.devtools.build.lib.skylarkinterface.StarlarkContext;
+import com.google.devtools.build.skyframe.EvaluationResult;
+import com.google.devtools.build.skyframe.SkyKey;
+import javax.annotation.Nullable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+import org.mockito.Mockito;
+
+/**
+ * Tests for {@link SingleToolchainResolutionValue} and {@link SingleToolchainResolutionFunction}.
+ */
+@RunWith(JUnit4.class)
+public class SingleToolchainResolutionFunctionTest extends ToolchainTestCase {
+  @AutoCodec @AutoCodec.VisibleForSerialization
+  static final ConfiguredTargetKey LINUX_CTKEY = Mockito.mock(ConfiguredTargetKey.class);
+
+  @AutoCodec @AutoCodec.VisibleForSerialization
+  static final ConfiguredTargetKey MAC_CTKEY = Mockito.mock(ConfiguredTargetKey.class);
+
+  static {
+    Mockito.when(LINUX_CTKEY.functionName())
+        .thenReturn(InjectedActionLookupKey.INJECTED_ACTION_LOOKUP);
+    Mockito.when(MAC_CTKEY.functionName())
+        .thenReturn(InjectedActionLookupKey.INJECTED_ACTION_LOOKUP);
+  }
+
+  private static ConfiguredTargetValue createConfiguredTargetValue(
+      ConfiguredTarget configuredTarget) {
+    return new NonRuleConfiguredTargetValue(
+        configuredTarget,
+        GeneratingActions.EMPTY,
+        NestedSetBuilder.emptySet(Order.STABLE_ORDER),
+        /*nonceVersion=*/ null);
+  }
+
+  private EvaluationResult<SingleToolchainResolutionValue> invokeToolchainResolution(SkyKey key)
+      throws InterruptedException {
+    ConfiguredTarget mockLinuxTarget = new SerializableConfiguredTarget(linuxPlatform);
+    ConfiguredTarget mockMacTarget = new SerializableConfiguredTarget(macPlatform);
+    getSkyframeExecutor()
+        .getDifferencerForTesting()
+        .inject(
+            ImmutableMap.of(
+                LINUX_CTKEY,
+                createConfiguredTargetValue(mockLinuxTarget),
+                MAC_CTKEY,
+                createConfiguredTargetValue(mockMacTarget)));
+
+    try {
+      getSkyframeExecutor().getSkyframeBuildView().enableAnalysis(true);
+      return SkyframeExecutorTestUtils.evaluate(
+          getSkyframeExecutor(), key, /*keepGoing=*/ false, reporter);
+    } finally {
+      getSkyframeExecutor().getSkyframeBuildView().enableAnalysis(false);
+    }
+  }
+
+  @Test
+  public void testResolution_singleExecutionPlatform() throws Exception {
+    SkyKey key =
+        SingleToolchainResolutionValue.key(
+            targetConfigKey, testToolchainTypeLabel, LINUX_CTKEY, ImmutableList.of(MAC_CTKEY));
+    EvaluationResult<SingleToolchainResolutionValue> result = invokeToolchainResolution(key);
+
+    assertThatEvaluationResult(result).hasNoError();
+
+    SingleToolchainResolutionValue singleToolchainResolutionValue = result.get(key);
+    assertThat(singleToolchainResolutionValue.availableToolchainLabels())
+        .containsExactly(MAC_CTKEY, makeLabel("//toolchain:toolchain_2_impl"));
+  }
+
+  @Test
+  public void testResolution_multipleExecutionPlatforms() throws Exception {
+    addToolchain(
+        "extra",
+        "extra_toolchain",
+        ImmutableList.of("//constraints:linux"),
+        ImmutableList.of("//constraints:linux"),
+        "baz");
+    rewriteWorkspace(
+        "register_toolchains(",
+        "'//toolchain:toolchain_1',",
+        "'//toolchain:toolchain_2',",
+        "'//extra:extra_toolchain')");
+
+    SkyKey key =
+        SingleToolchainResolutionValue.key(
+            targetConfigKey,
+            testToolchainTypeLabel,
+            LINUX_CTKEY,
+            ImmutableList.of(LINUX_CTKEY, MAC_CTKEY));
+    EvaluationResult<SingleToolchainResolutionValue> result = invokeToolchainResolution(key);
+
+    assertThatEvaluationResult(result).hasNoError();
+
+    SingleToolchainResolutionValue singleToolchainResolutionValue = result.get(key);
+    assertThat(singleToolchainResolutionValue.availableToolchainLabels())
+        .containsExactly(
+            LINUX_CTKEY,
+            makeLabel("//extra:extra_toolchain_impl"),
+            MAC_CTKEY,
+            makeLabel("//toolchain:toolchain_2_impl"));
+  }
+
+  @Test
+  public void testResolution_noneFound() throws Exception {
+    // Clear the toolchains.
+    rewriteWorkspace();
+
+    SkyKey key =
+        SingleToolchainResolutionValue.key(
+            targetConfigKey, testToolchainTypeLabel, LINUX_CTKEY, ImmutableList.of(MAC_CTKEY));
+    EvaluationResult<SingleToolchainResolutionValue> result = invokeToolchainResolution(key);
+
+    assertThatEvaluationResult(result)
+        .hasErrorEntryForKeyThat(key)
+        .hasExceptionThat()
+        .hasMessageThat()
+        .contains("no matching toolchain found for //toolchain:test_toolchain");
+  }
+
+  @Test
+  public void testToolchainResolutionValue_equalsAndHashCode() {
+    new EqualsTester()
+        .addEqualityGroup(
+            SingleToolchainResolutionValue.create(
+                testToolchainType,
+                ImmutableMap.of(LINUX_CTKEY, makeLabel("//test:toolchain_impl_1"))),
+            SingleToolchainResolutionValue.create(
+                testToolchainType,
+                ImmutableMap.of(LINUX_CTKEY, makeLabel("//test:toolchain_impl_1"))))
+        // Different execution platform, same label.
+        .addEqualityGroup(
+            SingleToolchainResolutionValue.create(
+                testToolchainType,
+                ImmutableMap.of(MAC_CTKEY, makeLabel("//test:toolchain_impl_1"))))
+        // Same execution platform, different label.
+        .addEqualityGroup(
+            SingleToolchainResolutionValue.create(
+                testToolchainType,
+                ImmutableMap.of(LINUX_CTKEY, makeLabel("//test:toolchain_impl_2"))))
+        // Different execution platform, different label.
+        .addEqualityGroup(
+            SingleToolchainResolutionValue.create(
+                testToolchainType,
+                ImmutableMap.of(MAC_CTKEY, makeLabel("//test:toolchain_impl_2"))))
+        // Multiple execution platforms.
+        .addEqualityGroup(
+            SingleToolchainResolutionValue.create(
+                testToolchainType,
+                ImmutableMap.<ConfiguredTargetKey, Label>builder()
+                    .put(LINUX_CTKEY, makeLabel("//test:toolchain_impl_1"))
+                    .put(MAC_CTKEY, makeLabel("//test:toolchain_impl_1"))
+                    .build()))
+        .testEquals();
+  }
+
+  /** Use custom class instead of mock to make sure that the dynamic codecs lookup is correct. */
+  class SerializableConfiguredTarget implements ConfiguredTarget {
+
+    private final PlatformInfo platform;
+
+    SerializableConfiguredTarget(PlatformInfo platform) {
+      this.platform = platform;
+    }
+
+    @Override
+    public ImmutableCollection<String> getFieldNames() {
+      return null;
+    }
+
+    @Nullable
+    @Override
+    public String getErrorMessageForUnknownField(String field) {
+      return null;
+    }
+
+    @Nullable
+    @Override
+    public Object getValue(String name) {
+      return null;
+    }
+
+    @Override
+    public Label getLabel() {
+      return null;
+    }
+
+    @Nullable
+    @Override
+    public BuildConfigurationValue.Key getConfigurationKey() {
+      return null;
+    }
+
+    @Nullable
+    @Override
+    public <P extends TransitiveInfoProvider> P getProvider(Class<P> provider) {
+      return null;
+    }
+
+    @Nullable
+    @Override
+    public Object get(String providerKey) {
+      return null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T extends InfoInterface> T get(NativeProvider<T> provider) {
+      if (PlatformInfo.PROVIDER.equals(provider)) {
+        return (T) this.platform;
+      }
+      return provider.getValueClass().cast(get(provider.getKey()));
+    }
+
+    @Nullable
+    @Override
+    public InfoInterface get(Provider.Key providerKey) {
+
+      return null;
+    }
+
+    @Override
+    public void repr(SkylarkPrinter printer) {}
+
+    @Override
+    public Object getIndex(Object key, Location loc, StarlarkContext context) {
+      return null;
+    }
+
+    @Override
+    public boolean containsKey(Object key, Location loc, StarlarkContext context) {
+      return false;
+    }
+  }
+}