aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/ConstraintValueLookupUtil.java140
-rw-r--r--src/main/java/com/google/devtools/build/lib/skyframe/ToolchainUtil.java72
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/ConstraintValueLookupUtilTest.java204
-rw-r--r--src/test/java/com/google/devtools/build/lib/skyframe/ToolchainUtilTest.java2
4 files changed, 348 insertions, 70 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ConstraintValueLookupUtil.java b/src/main/java/com/google/devtools/build/lib/skyframe/ConstraintValueLookupUtil.java
new file mode 100644
index 0000000000..4d3dc09b43
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ConstraintValueLookupUtil.java
@@ -0,0 +1,140 @@
+// Copyright 2018 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 com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
+import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.NoSuchThingException;
+import com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.ConfiguredValueCreationException;
+import com.google.devtools.build.skyframe.SkyFunction.Environment;
+import com.google.devtools.build.skyframe.SkyFunctionException;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.ValueOrException3;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
+
+/** Helper class that looks up {@link ConstraintValueInfo} data. */
+public class ConstraintValueLookupUtil {
+
+ @Nullable
+ public static List<ConstraintValueInfo> getConstraintValueInfo(
+ Iterable<ConfiguredTargetKey> constraintValueKeys, Environment env)
+ throws InterruptedException, InvalidConstraintValueException {
+
+ Map<
+ SkyKey,
+ ValueOrException3<
+ ConfiguredValueCreationException, NoSuchThingException, ActionConflictException>>
+ values =
+ env.getValuesOrThrow(
+ constraintValueKeys,
+ ConfiguredValueCreationException.class,
+ NoSuchThingException.class,
+ ActionConflictException.class);
+ boolean valuesMissing = env.valuesMissing();
+ List<ConstraintValueInfo> constraintValues = valuesMissing ? null : new ArrayList<>();
+ for (ConfiguredTargetKey key : constraintValueKeys) {
+ ConstraintValueInfo constraintValueInfo = findConstraintValueInfo(key, values.get(key));
+ if (!valuesMissing && constraintValueInfo != null) {
+ constraintValues.add(constraintValueInfo);
+ }
+ }
+ if (valuesMissing) {
+ return null;
+ }
+ return constraintValues;
+ }
+
+ /**
+ * Returns the {@link ConstraintValueInfo} provider from the {@link ConfiguredTarget} in the
+ * {@link ValueOrException3}, or {@code null} if the {@link ConfiguredTarget} is not present. If
+ * the {@link ConfiguredTarget} does not have a {@link ConstraintValueInfo} provider, a {@link
+ * InvalidConstraintValueException} is thrown.
+ */
+ @Nullable
+ private static ConstraintValueInfo findConstraintValueInfo(
+ ConfiguredTargetKey key,
+ ValueOrException3<
+ ConfiguredValueCreationException, NoSuchThingException, ActionConflictException>
+ valueOrException)
+ throws InvalidConstraintValueException {
+
+ try {
+ ConfiguredTargetValue ctv = (ConfiguredTargetValue) valueOrException.get();
+ if (ctv == null) {
+ return null;
+ }
+
+ ConfiguredTarget configuredTarget = ctv.getConfiguredTarget();
+ ConstraintValueInfo constraintValueInfo =
+ PlatformProviderUtils.constraintValue(configuredTarget);
+ if (constraintValueInfo == null) {
+ throw new InvalidConstraintValueException(configuredTarget.getLabel());
+ }
+
+ return constraintValueInfo;
+ } catch (ConfiguredValueCreationException e) {
+ throw new InvalidConstraintValueException(key.getLabel(), e);
+ } catch (NoSuchThingException e) {
+ throw new InvalidConstraintValueException(key.getLabel(), e);
+ } catch (ActionConflictException e) {
+ throw new InvalidConstraintValueException(key.getLabel(), e);
+ }
+ }
+
+ /** Exception used when a constraint value label is not a valid constraint value. */
+ public static final class InvalidConstraintValueException extends ToolchainException {
+ InvalidConstraintValueException(Label label) {
+ super(formatError(label));
+ }
+
+ InvalidConstraintValueException(Label label, ConfiguredValueCreationException e) {
+ super(formatError(label), e);
+ }
+
+ public InvalidConstraintValueException(Label label, NoSuchThingException e) {
+ // Just propagate the inner exception, because it's directly actionable.
+ super(e);
+ }
+
+ public InvalidConstraintValueException(Label label, ActionConflictException e) {
+ super(formatError(label), e);
+ }
+
+ private static String formatError(Label label) {
+ return String.format(
+ "Target %s was referenced as a constraint_value, "
+ + "but does not provide ConstraintValueInfo",
+ label);
+ }
+ }
+
+ /**
+ * Used to declare all the exception types that can be wrapped in the exception thrown by {@link
+ * #compute}.
+ */
+ public static class ConstraintValueLookupFunctionException extends SkyFunctionException {
+
+ public ConstraintValueLookupFunctionException(
+ InvalidConstraintValueException cause, Transience transience) {
+ super(cause, transience);
+ }
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainUtil.java b/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainUtil.java
index 156f62e05c..443959b284 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainUtil.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/ToolchainUtil.java
@@ -24,19 +24,17 @@ import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Table;
-import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.PlatformConfiguration;
import com.google.devtools.build.lib.analysis.PlatformOptions;
import com.google.devtools.build.lib.analysis.ToolchainContext;
import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
import com.google.devtools.build.lib.analysis.platform.PlatformInfo;
-import com.google.devtools.build.lib.analysis.platform.PlatformProviderUtils;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.TargetParsingException;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.pkgcache.FilteringPolicy;
-import com.google.devtools.build.lib.skyframe.ConfiguredTargetFunction.ConfiguredValueCreationException;
+import com.google.devtools.build.lib.skyframe.ConstraintValueLookupUtil.InvalidConstraintValueException;
import com.google.devtools.build.lib.skyframe.PlatformLookupUtil.InvalidPlatformException;
import com.google.devtools.build.lib.skyframe.RegisteredToolchainsFunction.InvalidToolchainLabelException;
import com.google.devtools.build.lib.skyframe.ToolchainResolutionFunction.NoToolchainFoundException;
@@ -419,7 +417,8 @@ public class ToolchainUtil {
if (platformInfoMap == null) {
return null;
}
- List<ConstraintValueInfo> constraints = getConstraintValueInfo(constraintKeys, env);
+ List<ConstraintValueInfo> constraints =
+ ConstraintValueLookupUtil.getConstraintValueInfo(constraintKeys, env);
if (constraints == null) {
return null;
}
@@ -430,53 +429,6 @@ public class ToolchainUtil {
.collect(toImmutableList());
}
- @Nullable
- private static List<ConstraintValueInfo> getConstraintValueInfo(
- ImmutableList<ConfiguredTargetKey> constraintKeys, Environment env)
- throws InterruptedException, InvalidConstraintValueException {
-
- Map<SkyKey, ValueOrException<ConfiguredValueCreationException>> values =
- env.getValuesOrThrow(constraintKeys, ConfiguredValueCreationException.class);
- boolean valuesMissing = env.valuesMissing();
- List<ConstraintValueInfo> constraintValues = valuesMissing ? null : new ArrayList<>();
- for (ConfiguredTargetKey key : constraintKeys) {
- ConstraintValueInfo constraintValueInfo =
- findConstraintValueInfo(key.getLabel(), values.get(key));
- if (!valuesMissing && constraintValueInfo != null) {
- constraintValues.add(constraintValueInfo);
- }
- }
-
- if (valuesMissing) {
- return null;
- }
- return constraintValues;
- }
-
- @Nullable
- private static ConstraintValueInfo findConstraintValueInfo(
- Label label, ValueOrException<ConfiguredValueCreationException> valueOrException)
- throws InvalidConstraintValueException {
-
- try {
- ConfiguredTargetValue configuredTargetValue = (ConfiguredTargetValue) valueOrException.get();
- if (configuredTargetValue == null) {
- return null;
- }
-
- ConfiguredTarget configuredTarget = configuredTargetValue.getConfiguredTarget();
- ConstraintValueInfo constraintValueInfo =
- PlatformProviderUtils.constraintValue(configuredTarget);
- if (constraintValueInfo == null) {
- throw new InvalidConstraintValueException(label);
- }
-
- return constraintValueInfo;
- } catch (ConfiguredValueCreationException e) {
- throw new InvalidConstraintValueException(label, e);
- }
- }
-
private static boolean filterPlatform(
PlatformInfo platformInfo,
List<ConstraintValueInfo> constraints,
@@ -566,24 +518,6 @@ public class ToolchainUtil {
}
}
- /** Exception used when a constraint value label is not a valid constraint value. */
- static final class InvalidConstraintValueException extends ToolchainException {
- InvalidConstraintValueException(Label label) {
- super(formatError(label));
- }
-
- InvalidConstraintValueException(Label label, ConfiguredValueCreationException e) {
- super(formatError(label), e);
- }
-
- private static String formatError(Label label) {
- return String.format(
- "Target %s was referenced as a constraint_value,"
- + " but does not provide ConstraintValueInfo",
- label);
- }
- }
-
/** Exception used when a toolchain type is required but no matching toolchain is found. */
public static final class UnresolvedToolchainsException extends ToolchainException {
private final ImmutableList<Label> missingToolchainTypes;
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ConstraintValueLookupUtilTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ConstraintValueLookupUtilTest.java
new file mode 100644
index 0000000000..fe9f0fff67
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ConstraintValueLookupUtilTest.java
@@ -0,0 +1,204 @@
+// Copyright 2018 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.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.analysis.BlazeDirectories;
+import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
+import com.google.devtools.build.lib.analysis.util.AnalysisMock;
+import com.google.devtools.build.lib.rules.platform.ToolchainTestCase;
+import com.google.devtools.build.lib.skyframe.ConstraintValueLookupUtil.InvalidConstraintValueException;
+import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils;
+import com.google.devtools.build.skyframe.EvaluationResult;
+import com.google.devtools.build.skyframe.SkyFunction;
+import com.google.devtools.build.skyframe.SkyFunctionException;
+import com.google.devtools.build.skyframe.SkyFunctionName;
+import com.google.devtools.build.skyframe.SkyKey;
+import com.google.devtools.build.skyframe.SkyValue;
+import java.util.List;
+import javax.annotation.Nullable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/** Tests for {@link ConstraintValueLookupUtil}. */
+@RunWith(JUnit4.class)
+public class ConstraintValueLookupUtilTest extends ToolchainTestCase {
+
+ /**
+ * An {@link AnalysisMock} that injects {@link GetConstraintValueInfoFunction} into the Skyframe
+ * executor.
+ */
+ private static final class AnalysisMockWithGetPlatformInfoFunction extends AnalysisMock.Delegate {
+ AnalysisMockWithGetPlatformInfoFunction() {
+ super(AnalysisMock.get());
+ }
+
+ @Override
+ public ImmutableMap<SkyFunctionName, SkyFunction> getSkyFunctions(
+ BlazeDirectories directories) {
+ return ImmutableMap.<SkyFunctionName, SkyFunction>builder()
+ .putAll(super.getSkyFunctions(directories))
+ .put(GET_CONSTRAINT_VALUE_INFO_FUNCTION, new GetConstraintValueInfoFunction())
+ .build();
+ }
+ }
+
+ @Override
+ protected AnalysisMock getAnalysisMock() {
+ return new AnalysisMockWithGetPlatformInfoFunction();
+ }
+
+ @Test
+ public void testConstraintValueLookup() throws Exception {
+ ConfiguredTargetKey linuxKey =
+ ConfiguredTargetKey.of(makeLabel("//constraints:linux"), targetConfigKey, false);
+ ConfiguredTargetKey macKey =
+ ConfiguredTargetKey.of(makeLabel("//constraints:mac"), targetConfigKey, false);
+ GetConstraintValueInfoKey key =
+ GetConstraintValueInfoKey.create(ImmutableList.of(linuxKey, macKey));
+
+ EvaluationResult<GetConstraintValueInfoValue> result = getConstraintValueInfo(key);
+
+ assertThatEvaluationResult(result).hasNoError();
+ assertThatEvaluationResult(result).hasEntryThat(key).isNotNull();
+
+ List<ConstraintValueInfo> constraintValues = result.get(key).constraintValues();
+ assertThat(constraintValues).contains(linuxConstraint);
+ assertThat(constraintValues).contains(macConstraint);
+ assertThat(constraintValues).hasSize(2);
+ }
+
+ @Test
+ public void testConstraintValueLookup_targetNotConstraintValue() throws Exception {
+ scratch.file("invalid/BUILD", "filegroup(name = 'not_a_constraint')");
+
+ ConfiguredTargetKey targetKey =
+ ConfiguredTargetKey.of(makeLabel("//invalid:not_a_constraint"), targetConfigKey, false);
+ GetConstraintValueInfoKey key = GetConstraintValueInfoKey.create(ImmutableList.of(targetKey));
+
+ EvaluationResult<GetConstraintValueInfoValue> result = getConstraintValueInfo(key);
+
+ assertThatEvaluationResult(result).hasError();
+ assertThatEvaluationResult(result)
+ .hasErrorEntryForKeyThat(key)
+ .hasExceptionThat()
+ .isInstanceOf(InvalidConstraintValueException.class);
+ assertThatEvaluationResult(result)
+ .hasErrorEntryForKeyThat(key)
+ .hasExceptionThat()
+ .hasMessageThat()
+ .contains("//invalid:not_a_constraint");
+ }
+
+ @Test
+ public void testConstraintValueLookup_targetDoesNotExist() throws Exception {
+ ConfiguredTargetKey targetKey =
+ ConfiguredTargetKey.of(makeLabel("//fake:missing"), targetConfigKey, false);
+ GetConstraintValueInfoKey key = GetConstraintValueInfoKey.create(ImmutableList.of(targetKey));
+
+ EvaluationResult<GetConstraintValueInfoValue> result = getConstraintValueInfo(key);
+
+ assertThatEvaluationResult(result).hasError();
+ assertThatEvaluationResult(result)
+ .hasErrorEntryForKeyThat(key)
+ .hasExceptionThat()
+ .isInstanceOf(InvalidConstraintValueException.class);
+ assertThatEvaluationResult(result)
+ .hasErrorEntryForKeyThat(key)
+ .hasExceptionThat()
+ .hasMessageThat()
+ .contains("no such package 'fake': BUILD file not found on package path");
+ }
+
+ // Calls ConstraintValueLookupUtil.getConstraintValueInfo.
+ private static final SkyFunctionName GET_CONSTRAINT_VALUE_INFO_FUNCTION =
+ SkyFunctionName.createHermetic("GET_CONSTRAINT_VALUE_INFO_FUNCTION");
+
+ @AutoValue
+ abstract static class GetConstraintValueInfoKey implements SkyKey {
+ @Override
+ public SkyFunctionName functionName() {
+ return GET_CONSTRAINT_VALUE_INFO_FUNCTION;
+ }
+
+ abstract Iterable<ConfiguredTargetKey> constraintValueKeys();
+
+ public static GetConstraintValueInfoKey create(
+ Iterable<ConfiguredTargetKey> constraintValueKeys) {
+ return new AutoValue_ConstraintValueLookupUtilTest_GetConstraintValueInfoKey(
+ constraintValueKeys);
+ }
+ }
+
+ EvaluationResult<GetConstraintValueInfoValue> getConstraintValueInfo(
+ GetConstraintValueInfoKey key) throws InterruptedException {
+ try {
+ // Must re-enable analysis for Skyframe functions that create configured targets.
+ skyframeExecutor.getSkyframeBuildView().enableAnalysis(true);
+ return SkyframeExecutorTestUtils.evaluate(
+ skyframeExecutor, key, /*keepGoing=*/ false, reporter);
+ } finally {
+ skyframeExecutor.getSkyframeBuildView().enableAnalysis(false);
+ }
+ }
+
+ @AutoValue
+ abstract static class GetConstraintValueInfoValue implements SkyValue {
+ abstract List<ConstraintValueInfo> constraintValues();
+
+ static GetConstraintValueInfoValue create(List<ConstraintValueInfo> constraintValues) {
+ return new AutoValue_ConstraintValueLookupUtilTest_GetConstraintValueInfoValue(
+ constraintValues);
+ }
+ }
+
+ private static final class GetConstraintValueInfoFunction implements SkyFunction {
+
+ @Nullable
+ @Override
+ public SkyValue compute(SkyKey skyKey, Environment env)
+ throws SkyFunctionException, InterruptedException {
+ GetConstraintValueInfoKey key = (GetConstraintValueInfoKey) skyKey;
+ try {
+ List<ConstraintValueInfo> constraintValues =
+ ConstraintValueLookupUtil.getConstraintValueInfo(key.constraintValueKeys(), env);
+ if (env.valuesMissing()) {
+ return null;
+ }
+ return GetConstraintValueInfoValue.create(constraintValues);
+ } catch (InvalidConstraintValueException e) {
+ throw new GetConstraintValueInfoFunctionException(e);
+ }
+ }
+
+ @Nullable
+ @Override
+ public String extractTag(SkyKey skyKey) {
+ return null;
+ }
+ }
+
+ private static class GetConstraintValueInfoFunctionException extends SkyFunctionException {
+ public GetConstraintValueInfoFunctionException(InvalidConstraintValueException e) {
+ super(e, Transience.PERSISTENT);
+ }
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainUtilTest.java b/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainUtilTest.java
index 7a7dbabf61..8d7720657f 100644
--- a/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainUtilTest.java
+++ b/src/test/java/com/google/devtools/build/lib/skyframe/ToolchainUtilTest.java
@@ -26,8 +26,8 @@ import com.google.devtools.build.lib.analysis.ToolchainContext;
import com.google.devtools.build.lib.analysis.util.AnalysisMock;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.rules.platform.ToolchainTestCase;
+import com.google.devtools.build.lib.skyframe.ConstraintValueLookupUtil.InvalidConstraintValueException;
import com.google.devtools.build.lib.skyframe.PlatformLookupUtil.InvalidPlatformException;
-import com.google.devtools.build.lib.skyframe.ToolchainUtil.InvalidConstraintValueException;
import com.google.devtools.build.lib.skyframe.ToolchainUtil.NoMatchingPlatformException;
import com.google.devtools.build.lib.skyframe.ToolchainUtil.UnresolvedToolchainsException;
import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils;