blob: 8ea6d9df7b2e21b5b7be5d005c4e01fd547f826a [file] [log] [blame]
John Caterdfce7402018-07-17 13:23:44 -07001// Copyright 2018 The Bazel Authors. All rights reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package com.google.devtools.build.lib.skyframe;
16
17import static com.google.common.truth.Truth.assertThat;
18import static com.google.devtools.build.skyframe.EvaluationResultSubjectFactory.assertThatEvaluationResult;
19
20import com.google.auto.value.AutoValue;
21import com.google.common.collect.ImmutableList;
22import com.google.common.collect.ImmutableMap;
23import com.google.devtools.build.lib.analysis.BlazeDirectories;
24import com.google.devtools.build.lib.analysis.platform.ConstraintValueInfo;
25import com.google.devtools.build.lib.analysis.util.AnalysisMock;
John Cater2571a952021-03-23 13:26:32 -070026import com.google.devtools.build.lib.cmdline.Label;
John Caterdfce7402018-07-17 13:23:44 -070027import com.google.devtools.build.lib.rules.platform.ToolchainTestCase;
28import com.google.devtools.build.lib.skyframe.ConstraintValueLookupUtil.InvalidConstraintValueException;
29import com.google.devtools.build.lib.skyframe.util.SkyframeExecutorTestUtils;
30import com.google.devtools.build.skyframe.EvaluationResult;
31import com.google.devtools.build.skyframe.SkyFunction;
32import com.google.devtools.build.skyframe.SkyFunctionException;
33import com.google.devtools.build.skyframe.SkyFunctionName;
34import com.google.devtools.build.skyframe.SkyKey;
35import com.google.devtools.build.skyframe.SkyValue;
36import java.util.List;
37import javax.annotation.Nullable;
38import org.junit.Test;
39import org.junit.runner.RunWith;
40import org.junit.runners.JUnit4;
41
42/** Tests for {@link ConstraintValueLookupUtil}. */
43@RunWith(JUnit4.class)
44public class ConstraintValueLookupUtilTest extends ToolchainTestCase {
45
46 /**
47 * An {@link AnalysisMock} that injects {@link GetConstraintValueInfoFunction} into the Skyframe
48 * executor.
49 */
50 private static final class AnalysisMockWithGetPlatformInfoFunction extends AnalysisMock.Delegate {
51 AnalysisMockWithGetPlatformInfoFunction() {
52 super(AnalysisMock.get());
53 }
54
55 @Override
56 public ImmutableMap<SkyFunctionName, SkyFunction> getSkyFunctions(
57 BlazeDirectories directories) {
58 return ImmutableMap.<SkyFunctionName, SkyFunction>builder()
59 .putAll(super.getSkyFunctions(directories))
60 .put(GET_CONSTRAINT_VALUE_INFO_FUNCTION, new GetConstraintValueInfoFunction())
Googler0ef92252022-02-01 03:58:42 -080061 .buildOrThrow();
John Caterdfce7402018-07-17 13:23:44 -070062 }
63 }
64
65 @Override
66 protected AnalysisMock getAnalysisMock() {
67 return new AnalysisMockWithGetPlatformInfoFunction();
68 }
69
70 @Test
71 public void testConstraintValueLookup() throws Exception {
72 ConfiguredTargetKey linuxKey =
jcater83221e32020-05-28 11:37:39 -070073 ConfiguredTargetKey.builder()
Googler08463dc2023-01-20 08:02:19 -080074 .setLabel(Label.parseCanonicalUnchecked("//constraints:linux"))
jcater83221e32020-05-28 11:37:39 -070075 .setConfigurationKey(targetConfigKey)
76 .build();
John Caterdfce7402018-07-17 13:23:44 -070077 ConfiguredTargetKey macKey =
jcater83221e32020-05-28 11:37:39 -070078 ConfiguredTargetKey.builder()
Googler08463dc2023-01-20 08:02:19 -080079 .setLabel(Label.parseCanonicalUnchecked("//constraints:mac"))
jcater83221e32020-05-28 11:37:39 -070080 .setConfigurationKey(targetConfigKey)
81 .build();
John Caterdfce7402018-07-17 13:23:44 -070082 GetConstraintValueInfoKey key =
83 GetConstraintValueInfoKey.create(ImmutableList.of(linuxKey, macKey));
84
85 EvaluationResult<GetConstraintValueInfoValue> result = getConstraintValueInfo(key);
86
87 assertThatEvaluationResult(result).hasNoError();
88 assertThatEvaluationResult(result).hasEntryThat(key).isNotNull();
89
90 List<ConstraintValueInfo> constraintValues = result.get(key).constraintValues();
91 assertThat(constraintValues).contains(linuxConstraint);
92 assertThat(constraintValues).contains(macConstraint);
93 assertThat(constraintValues).hasSize(2);
94 }
95
96 @Test
97 public void testConstraintValueLookup_targetNotConstraintValue() throws Exception {
98 scratch.file("invalid/BUILD", "filegroup(name = 'not_a_constraint')");
99
100 ConfiguredTargetKey targetKey =
jcater83221e32020-05-28 11:37:39 -0700101 ConfiguredTargetKey.builder()
Googler08463dc2023-01-20 08:02:19 -0800102 .setLabel(Label.parseCanonicalUnchecked("//invalid:not_a_constraint"))
jcater83221e32020-05-28 11:37:39 -0700103 .setConfigurationKey(targetConfigKey)
104 .build();
John Caterdfce7402018-07-17 13:23:44 -0700105 GetConstraintValueInfoKey key = GetConstraintValueInfoKey.create(ImmutableList.of(targetKey));
106
107 EvaluationResult<GetConstraintValueInfoValue> result = getConstraintValueInfo(key);
108
109 assertThatEvaluationResult(result).hasError();
110 assertThatEvaluationResult(result)
111 .hasErrorEntryForKeyThat(key)
112 .hasExceptionThat()
113 .isInstanceOf(InvalidConstraintValueException.class);
114 assertThatEvaluationResult(result)
115 .hasErrorEntryForKeyThat(key)
116 .hasExceptionThat()
117 .hasMessageThat()
118 .contains("//invalid:not_a_constraint");
119 }
120
121 @Test
122 public void testConstraintValueLookup_targetDoesNotExist() throws Exception {
123 ConfiguredTargetKey targetKey =
jcater83221e32020-05-28 11:37:39 -0700124 ConfiguredTargetKey.builder()
Googler08463dc2023-01-20 08:02:19 -0800125 .setLabel(Label.parseCanonicalUnchecked("//fake:missing"))
jcater83221e32020-05-28 11:37:39 -0700126 .setConfigurationKey(targetConfigKey)
127 .build();
John Caterdfce7402018-07-17 13:23:44 -0700128 GetConstraintValueInfoKey key = GetConstraintValueInfoKey.create(ImmutableList.of(targetKey));
129
130 EvaluationResult<GetConstraintValueInfoValue> result = getConstraintValueInfo(key);
131
132 assertThatEvaluationResult(result).hasError();
133 assertThatEvaluationResult(result)
134 .hasErrorEntryForKeyThat(key)
135 .hasExceptionThat()
136 .isInstanceOf(InvalidConstraintValueException.class);
137 assertThatEvaluationResult(result)
138 .hasErrorEntryForKeyThat(key)
139 .hasExceptionThat()
140 .hasMessageThat()
Klaus Aehligca5565a2019-05-07 05:43:58 -0700141 .contains("no such package 'fake': BUILD file not found");
John Caterdfce7402018-07-17 13:23:44 -0700142 }
143
144 // Calls ConstraintValueLookupUtil.getConstraintValueInfo.
145 private static final SkyFunctionName GET_CONSTRAINT_VALUE_INFO_FUNCTION =
146 SkyFunctionName.createHermetic("GET_CONSTRAINT_VALUE_INFO_FUNCTION");
147
148 @AutoValue
149 abstract static class GetConstraintValueInfoKey implements SkyKey {
150 @Override
151 public SkyFunctionName functionName() {
152 return GET_CONSTRAINT_VALUE_INFO_FUNCTION;
153 }
154
155 abstract Iterable<ConfiguredTargetKey> constraintValueKeys();
156
157 public static GetConstraintValueInfoKey create(
158 Iterable<ConfiguredTargetKey> constraintValueKeys) {
159 return new AutoValue_ConstraintValueLookupUtilTest_GetConstraintValueInfoKey(
160 constraintValueKeys);
161 }
162 }
163
164 EvaluationResult<GetConstraintValueInfoValue> getConstraintValueInfo(
165 GetConstraintValueInfoKey key) throws InterruptedException {
166 try {
167 // Must re-enable analysis for Skyframe functions that create configured targets.
168 skyframeExecutor.getSkyframeBuildView().enableAnalysis(true);
169 return SkyframeExecutorTestUtils.evaluate(
170 skyframeExecutor, key, /*keepGoing=*/ false, reporter);
171 } finally {
172 skyframeExecutor.getSkyframeBuildView().enableAnalysis(false);
173 }
174 }
175
176 @AutoValue
177 abstract static class GetConstraintValueInfoValue implements SkyValue {
178 abstract List<ConstraintValueInfo> constraintValues();
179
180 static GetConstraintValueInfoValue create(List<ConstraintValueInfo> constraintValues) {
181 return new AutoValue_ConstraintValueLookupUtilTest_GetConstraintValueInfoValue(
182 constraintValues);
183 }
184 }
185
186 private static final class GetConstraintValueInfoFunction implements SkyFunction {
187
188 @Nullable
189 @Override
190 public SkyValue compute(SkyKey skyKey, Environment env)
191 throws SkyFunctionException, InterruptedException {
192 GetConstraintValueInfoKey key = (GetConstraintValueInfoKey) skyKey;
193 try {
194 List<ConstraintValueInfo> constraintValues =
195 ConstraintValueLookupUtil.getConstraintValueInfo(key.constraintValueKeys(), env);
196 if (env.valuesMissing()) {
197 return null;
198 }
199 return GetConstraintValueInfoValue.create(constraintValues);
200 } catch (InvalidConstraintValueException e) {
201 throw new GetConstraintValueInfoFunctionException(e);
202 }
203 }
John Caterdfce7402018-07-17 13:23:44 -0700204 }
205
206 private static class GetConstraintValueInfoFunctionException extends SkyFunctionException {
207 public GetConstraintValueInfoFunctionException(InvalidConstraintValueException e) {
208 super(e, Transience.PERSISTENT);
209 }
210 }
211}