blob: f6061cc2c76e948d526be5280fde79f1b8d89937 [file] [log] [blame]
juliexxiadeb028e2019-01-05 17:19:21 -08001// 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.
14package com.google.devtools.build.lib.analysis;
15
16import static com.google.common.truth.Truth.assertThat;
juliexxiadeb028e2019-01-05 17:19:21 -080017
juliexxia22de6cd2019-01-09 07:25:23 -080018import com.google.common.collect.ImmutableMap;
juliexxiadeb028e2019-01-05 17:19:21 -080019import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
gregce06b76c92020-06-19 14:46:56 -070020import com.google.devtools.build.lib.analysis.config.transitions.ConfigurationTransition;
juliexxiadeb028e2019-01-05 17:19:21 -080021import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
twigg4970e0f2021-03-31 15:34:49 -070022import com.google.devtools.build.lib.analysis.util.DummyTestFragment;
23import com.google.devtools.build.lib.analysis.util.DummyTestFragment.DummyTestOptions;
juliexxia22de6cd2019-01-09 07:25:23 -080024import com.google.devtools.build.lib.cmdline.Label;
gregce06b76c92020-06-19 14:46:56 -070025import com.google.devtools.build.lib.packages.Rule;
gregce7fc9ae72020-04-24 10:54:14 -070026import com.google.devtools.build.lib.rules.cpp.CppOptions;
gregce06b76c92020-06-19 14:46:56 -070027import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
gregced6795462020-12-14 11:06:45 -080028import com.google.devtools.build.lib.testutil.TestConstants;
juliexxia6778a052019-04-09 08:25:05 -070029import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
juliexxiaa13f5902020-12-10 09:19:01 -080030import java.util.List;
31import java.util.Map;
juliexxiadeb028e2019-01-05 17:19:21 -080032import org.junit.Test;
33import org.junit.runner.RunWith;
34import org.junit.runners.JUnit4;
35
juliexxia1a70c272019-04-09 09:33:23 -070036/** Tests for StarlarkRuleTransitionProvider. */
juliexxiadeb028e2019-01-05 17:19:21 -080037@RunWith(JUnit4.class)
38public class StarlarkRuleTransitionProviderTest extends BuildViewTestCase {
juliexxia6778a052019-04-09 08:25:05 -070039 @Override
brandjon232a6b82020-06-08 12:32:49 -070040 protected ConfiguredRuleClassProvider createRuleClassProvider() {
juliexxia6778a052019-04-09 08:25:05 -070041 ConfiguredRuleClassProvider.Builder builder = new ConfiguredRuleClassProvider.Builder();
42 TestRuleClassProvider.addStandardRules(builder);
gregce4ed65b02020-11-18 07:06:25 -080043 builder.addConfigurationFragment(DummyTestFragment.class);
juliexxia6778a052019-04-09 08:25:05 -070044 return builder.build();
45 }
46
aiuto50226ac2020-06-14 21:28:27 -070047 private void writeAllowlistFile() throws Exception {
juliexxia30976d82019-03-12 10:59:26 -070048 scratch.file(
cushon1812caf2020-06-24 10:54:19 -070049 "tools/allowlists/function_transition_allowlist/BUILD",
juliexxia30976d82019-03-12 10:59:26 -070050 "package_group(",
cushon1812caf2020-06-24 10:54:19 -070051 " name = 'function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -070052 " packages = [",
53 " '//test/...',",
54 " ],",
55 ")");
56 }
57
juliexxiadeb028e2019-01-05 17:19:21 -080058 @Test
juliexxiaeee87e92019-04-30 13:21:42 -070059 public void testBadReturnTypeFromTransition() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -070060 writeAllowlistFile();
juliexxiaeee87e92019-04-30 13:21:42 -070061 scratch.file(
62 "test/transitions.bzl",
63 "def _impl(settings, attr):",
64 " return 'cpu=k8'",
65 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -070066 " outputs = ['//command_line_option:foo'])");
juliexxiaeee87e92019-04-30 13:21:42 -070067 scratch.file(
68 "test/rules.bzl",
69 "load('//test:transitions.bzl', 'my_transition')",
70 "def _impl(ctx):",
71 " return []",
72 "my_rule = rule(",
73 " implementation = _impl,",
74 " cfg = my_transition,",
75 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -070076 " '_allowlist_function_transition': attr.label(",
77 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxiaeee87e92019-04-30 13:21:42 -070078 " ),",
79 " })");
80 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
81
82 reporter.removeHandler(failFastHandler);
83 getConfiguredTarget("//test");
adonovand07bf132021-01-08 09:10:22 -080084 assertContainsEvent("transition function returned string, want dict or list of dicts");
juliexxiaeee87e92019-04-30 13:21:42 -070085 }
86
87 @Test
juliexxiadeb028e2019-01-05 17:19:21 -080088 public void testOutputOnlyTransition() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -070089 writeAllowlistFile();
juliexxiadeb028e2019-01-05 17:19:21 -080090 scratch.file(
91 "test/transitions.bzl",
92 "def _impl(settings, attr):",
twigg4970e0f2021-03-31 15:34:49 -070093 " return {'//command_line_option:foo': 'post-transition'}",
juliexxiadeb028e2019-01-05 17:19:21 -080094 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -070095 " outputs = ['//command_line_option:foo'])");
juliexxiadeb028e2019-01-05 17:19:21 -080096 scratch.file(
97 "test/rules.bzl",
98 "load('//test:transitions.bzl', 'my_transition')",
99 "def _impl(ctx):",
100 " return []",
juliexxia30976d82019-03-12 10:59:26 -0700101 "my_rule = rule(",
102 " implementation = _impl,",
103 " cfg = my_transition,",
104 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700105 " '_allowlist_function_transition': attr.label(",
106 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700107 " ),",
108 " })");
juliexxiadeb028e2019-01-05 17:19:21 -0800109 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
110
twigg4970e0f2021-03-31 15:34:49 -0700111 useConfiguration("--foo=pre-transition");
juliexxiadeb028e2019-01-05 17:19:21 -0800112
113 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
twigg4970e0f2021-03-31 15:34:49 -0700114 assertThat(configuration.getOptions().get(DummyTestOptions.class).foo)
115 .isEqualTo("post-transition");
juliexxiadeb028e2019-01-05 17:19:21 -0800116 }
117
118 @Test
119 public void testInputAndOutputTransition() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700120 writeAllowlistFile();
juliexxiadeb028e2019-01-05 17:19:21 -0800121 scratch.file(
122 "test/transitions.bzl",
123 "def _impl(settings, attr):",
twigg4970e0f2021-03-31 15:34:49 -0700124 " return {'//command_line_option:foo': ",
125 " settings['//command_line_option:foo']+'->post-transition'}",
juliexxiadeb028e2019-01-05 17:19:21 -0800126 "my_transition = transition(",
127 " implementation = _impl,",
twigg4970e0f2021-03-31 15:34:49 -0700128 " inputs = ['//command_line_option:foo'],",
129 " outputs = ['//command_line_option:foo'],",
juliexxiadeb028e2019-01-05 17:19:21 -0800130 ")");
131
132 scratch.file(
133 "test/rules.bzl",
134 "load('//test:transitions.bzl', 'my_transition')",
135 "def _impl(ctx):",
136 " return []",
juliexxia30976d82019-03-12 10:59:26 -0700137 "my_rule = rule(",
138 " implementation = _impl,",
139 " cfg = my_transition,",
140 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700141 " '_allowlist_function_transition': attr.label(",
142 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700143 " ),",
144 " })");
juliexxiadeb028e2019-01-05 17:19:21 -0800145
146 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
147
twigg4970e0f2021-03-31 15:34:49 -0700148 useConfiguration("--foo=pre-transition");
juliexxiadeb028e2019-01-05 17:19:21 -0800149
150 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
twigg4970e0f2021-03-31 15:34:49 -0700151 assertThat(configuration.getOptions().get(DummyTestOptions.class).foo)
152 .isEqualTo("pre-transition->post-transition");
juliexxiadeb028e2019-01-05 17:19:21 -0800153 }
154
155 @Test
156 public void testBuildSettingCannotTransition() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700157 writeAllowlistFile();
juliexxiadeb028e2019-01-05 17:19:21 -0800158 scratch.file(
159 "test/transitions.bzl",
160 "def _impl(settings, attr):",
twigg4970e0f2021-03-31 15:34:49 -0700161 " return {'//command_line_option:foo': 'post-transition'}",
juliexxiadeb028e2019-01-05 17:19:21 -0800162 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -0700163 " outputs = ['//command_line_option:foo'])");
juliexxiadeb028e2019-01-05 17:19:21 -0800164 scratch.file(
165 "test/rules.bzl",
166 "load('//test:transitions.bzl', 'my_transition')",
167 "def _impl(ctx):",
168 " return []",
169 "my_rule = rule(",
170 " implementation = _impl,",
171 " cfg = my_transition,",
juliexxia30976d82019-03-12 10:59:26 -0700172 " build_setting = config.string(),",
173 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700174 " '_allowlist_function_transition': attr.label(",
175 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700176 " ),",
177 " })");
juliexxiadeb028e2019-01-05 17:19:21 -0800178 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
179
180 reporter.removeHandler(failFastHandler);
181 getConfiguredTarget("//test");
182 assertContainsEvent(
183 "Build setting rules cannot use the `cfg` param to apply transitions to themselves");
184 }
185
186 @Test
187 public void testBadCfgInput() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700188 writeAllowlistFile();
juliexxiadeb028e2019-01-05 17:19:21 -0800189 scratch.file(
190 "test/rules.bzl",
191 "def _impl(ctx):",
192 " return []",
193 "my_rule = rule(",
194 " implementation = _impl,",
195 " cfg = 'my_transition',",
juliexxia30976d82019-03-12 10:59:26 -0700196 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700197 " '_allowlist_function_transition': attr.label(",
198 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700199 " ),",
200 " })");
juliexxiadeb028e2019-01-05 17:19:21 -0800201 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
202
203 reporter.removeHandler(failFastHandler);
204 getConfiguredTarget("//test");
205 assertContainsEvent(
206 "`cfg` must be set to a transition object initialized by the transition() function.");
207 }
208
209 @Test
210 public void testMultipleReturnConfigs() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700211 writeAllowlistFile();
juliexxiadeb028e2019-01-05 17:19:21 -0800212 scratch.file(
213 "test/transitions.bzl",
214 "def _impl(settings, attr):",
juliexxiaeee87e92019-04-30 13:21:42 -0700215 " return [",
twigg4970e0f2021-03-31 15:34:49 -0700216 " {'//command_line_option:foo': 'split_one'},",
217 " {'//command_line_option:foo': 'split_two'},",
juliexxiaeee87e92019-04-30 13:21:42 -0700218 " ]",
juliexxiadeb028e2019-01-05 17:19:21 -0800219 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -0700220 " outputs = ['//command_line_option:foo'])");
juliexxiadeb028e2019-01-05 17:19:21 -0800221 scratch.file(
222 "test/rules.bzl",
223 "load('//test:transitions.bzl', 'my_transition')",
224 "def _impl(ctx):",
225 " return []",
juliexxia30976d82019-03-12 10:59:26 -0700226 "my_rule = rule(",
227 " implementation = _impl,",
228 " cfg = my_transition,",
229 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700230 " '_allowlist_function_transition': attr.label(",
231 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700232 " ),",
233 " })");
juliexxiadeb028e2019-01-05 17:19:21 -0800234 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
235
juliexxia03ff8782019-03-20 13:03:27 -0700236 reporter.removeHandler(failFastHandler);
juliexxiafb45b602019-04-01 12:10:30 -0700237 getConfiguredTarget("//test");
juliexxia03ff8782019-03-20 13:03:27 -0700238 assertContainsEvent(
239 "Rule transition only allowed to return a single transitioned configuration.");
juliexxiadeb028e2019-01-05 17:19:21 -0800240 }
241
242 @Test
243 public void testCanDoBadStuffWithParameterizedTransitionsAndSelects() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700244 writeAllowlistFile();
juliexxiadeb028e2019-01-05 17:19:21 -0800245 scratch.file(
246 "test/transitions.bzl",
247 "def _impl(settings, attr):",
248 " if (attr.my_configurable_attr):",
twigg4970e0f2021-03-31 15:34:49 -0700249 " return {'//command_line_option:foo': 'true'}",
juliexxiadeb028e2019-01-05 17:19:21 -0800250 " else:",
twigg4970e0f2021-03-31 15:34:49 -0700251 " return {'//command_line_option:foo': 'false'}",
juliexxiadeb028e2019-01-05 17:19:21 -0800252 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -0700253 " outputs = ['//command_line_option:foo'])");
juliexxiadeb028e2019-01-05 17:19:21 -0800254 scratch.file(
255 "test/rules.bzl",
256 "load('//test:transitions.bzl', 'my_transition')",
257 "def _impl(ctx):",
258 " return []",
259 "my_rule = rule(",
260 " implementation = _impl,",
261 " cfg = my_transition,",
juliexxia30976d82019-03-12 10:59:26 -0700262 " attrs = {",
263 " 'my_configurable_attr': attr.bool(default = False),",
cushon1812caf2020-06-24 10:54:19 -0700264 " '_allowlist_function_transition': attr.label(",
265 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700266 " ),",
267 " },",
juliexxiadeb028e2019-01-05 17:19:21 -0800268 ")");
269 scratch.file(
270 "test/BUILD",
271 "load('//test:rules.bzl', 'my_rule')",
272 "my_rule(",
273 " name = 'test',",
274 " my_configurable_attr = select({",
275 " '//conditions:default': False,",
276 " ':true-config': True,",
277 " })",
278 ")",
279 "config_setting(",
280 " name = 'true-config',",
twigg4970e0f2021-03-31 15:34:49 -0700281 " values = {'foo': 'true'},",
juliexxiadeb028e2019-01-05 17:19:21 -0800282 ")");
283
juliexxia03ff8782019-03-20 13:03:27 -0700284 reporter.removeHandler(failFastHandler);
juliexxiafb45b602019-04-01 12:10:30 -0700285 getConfiguredTarget("//test");
juliexxia03ff8782019-03-20 13:03:27 -0700286 assertContainsEvent(
287 "No attribute 'my_configurable_attr'. "
288 + "Either this attribute does not exist for this rule or is set by a select. "
289 + "Starlark rule transitions currently cannot read attributes behind selects.");
juliexxiadeb028e2019-01-05 17:19:21 -0800290 }
291
292 @Test
293 public void testLabelTypedAttrReturnsLabelNotDep() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700294 writeAllowlistFile();
juliexxiadeb028e2019-01-05 17:19:21 -0800295 scratch.file(
296 "test/transitions.bzl",
297 "def _impl(settings, attr):",
298 " if attr.dict_attr[Label('//test:key')] == 'value':",
twigg4970e0f2021-03-31 15:34:49 -0700299 " return {'//command_line_option:foo': 'post-transition'}",
juliexxiadeb028e2019-01-05 17:19:21 -0800300 " else:",
twigg4970e0f2021-03-31 15:34:49 -0700301 " return {'//command_line_option:foo': 'uh-oh'}",
juliexxiadeb028e2019-01-05 17:19:21 -0800302 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -0700303 " outputs = ['//command_line_option:foo'])");
juliexxiadeb028e2019-01-05 17:19:21 -0800304 scratch.file(
305 "test/rules.bzl",
306 "load('//test:transitions.bzl', 'my_transition')",
307 "def _impl(ctx):",
308 " return []",
309 "my_rule = rule(",
310 " implementation = _impl,",
311 " cfg = my_transition,",
juliexxia30976d82019-03-12 10:59:26 -0700312 " attrs = {",
313 " 'dict_attr': attr.label_keyed_string_dict(),",
cushon1812caf2020-06-24 10:54:19 -0700314 " '_allowlist_function_transition': attr.label(",
315 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700316 " ),",
317 " },",
juliexxiadeb028e2019-01-05 17:19:21 -0800318 ")",
319 "simple_rule = rule(_impl)");
320 scratch.file(
321 "test/BUILD",
322 "load('//test:rules.bzl', 'my_rule', 'simple_rule')",
323 "my_rule(",
324 " name = 'test',",
325 " dict_attr = {':key': 'value'},",
326 ")",
327 "simple_rule(name = 'key')");
328
twigg4970e0f2021-03-31 15:34:49 -0700329 useConfiguration("--foo=pre-transition");
juliexxiadeb028e2019-01-05 17:19:21 -0800330
331 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
twigg4970e0f2021-03-31 15:34:49 -0700332 assertThat(configuration.getOptions().get(DummyTestOptions.class).foo)
333 .isEqualTo("post-transition");
juliexxiadeb028e2019-01-05 17:19:21 -0800334 }
335
juliexxiadb566782019-04-12 10:48:07 -0700336 private static final String CUTE_ANIMAL_DEFAULT =
337 "cows produce more milk when they listen to soothing music";
338
juliexxia30976d82019-03-12 10:59:26 -0700339 private void writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700340 writeAllowlistFile();
juliexxia30976d82019-03-12 10:59:26 -0700341 scratch.file(
342 "test/rules.bzl",
343 "load('//test:transitions.bzl', 'my_transition')",
344 "def _rule_impl(ctx):",
345 " return []",
346 "my_rule = rule(",
347 " implementation = _rule_impl,",
348 " cfg = my_transition,",
349 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700350 " '_allowlist_function_transition': attr.label(",
351 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700352 " ),",
353 " },",
354 ")");
355
356 scratch.file(
357 "test/build_settings.bzl",
358 "def _impl(ctx):",
359 " return []",
360 "string_flag = rule(implementation = _impl, build_setting = config.string(flag=True))");
361
362 scratch.file(
363 "test/BUILD",
364 "load('//test:rules.bzl', 'my_rule')",
365 "load('//test:build_settings.bzl', 'string_flag')",
366 "my_rule(name = 'test')",
367 "string_flag(",
368 " name = 'cute-animal-fact',",
juliexxiadb566782019-04-12 10:48:07 -0700369 " build_setting_default = '" + CUTE_ANIMAL_DEFAULT + "',",
juliexxia30976d82019-03-12 10:59:26 -0700370 ")");
371 }
372
juliexxiadeb028e2019-01-05 17:19:21 -0800373 @Test
juliexxia03ff8782019-03-20 13:03:27 -0700374 public void testTransitionOnBuildSetting_fromDefault() throws Exception {
juliexxia03ff8782019-03-20 13:03:27 -0700375 scratch.file(
376 "test/transitions.bzl",
377 "def _transition_impl(settings, attr):",
378 " return {'//test:cute-animal-fact': 'puffins mate for life'}",
379 "my_transition = transition(",
380 " implementation = _transition_impl,",
381 " inputs = [],",
382 " outputs = ['//test:cute-animal-fact']",
383 ")");
384 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
385
386 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
387 assertThat(
388 configuration
389 .getOptions()
390 .getStarlarkOptions()
391 .get(Label.parseAbsoluteUnchecked("//test:cute-animal-fact")))
392 .isEqualTo("puffins mate for life");
393 }
394
395 @Test
396 public void testTransitionOnBuildSetting_fromCommandLine() throws Exception {
juliexxia22de6cd2019-01-09 07:25:23 -0800397 scratch.file(
398 "test/transitions.bzl",
399 "def _transition_impl(settings, attr):",
400 " return {'//test:cute-animal-fact': 'puffins mate for life'}",
401 "my_transition = transition(",
402 " implementation = _transition_impl,",
403 " inputs = [],",
404 " outputs = ['//test:cute-animal-fact']",
405 ")");
406 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
407
408 useConfiguration(ImmutableMap.of("//test:cute-animal-fact", "cats can't taste sugar"));
juliexxia03ff8782019-03-20 13:03:27 -0700409
juliexxia22de6cd2019-01-09 07:25:23 -0800410 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
411 assertThat(
412 configuration
413 .getOptions()
414 .getStarlarkOptions()
415 .get(Label.parseAbsoluteUnchecked("//test:cute-animal-fact")))
416 .isEqualTo("puffins mate for life");
417 }
418
juliexxia22de6cd2019-01-09 07:25:23 -0800419 @Test
juliexxia03ff8782019-03-20 13:03:27 -0700420 public void testTransitionOnBuildSetting_badValue() throws Exception {
juliexxia22de6cd2019-01-09 07:25:23 -0800421 scratch.file(
422 "test/transitions.bzl",
423 "def _transition_impl(settings, attr):",
424 " return {'//test:cute-animal-fact': 24}",
425 "my_transition = transition(",
426 " implementation = _transition_impl,",
427 " inputs = [],",
428 " outputs = ['//test:cute-animal-fact']",
429 ")");
430 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
431
432 useConfiguration(ImmutableMap.of("//test:cute-animal-fact", "cats can't taste sugar"));
juliexxia03ff8782019-03-20 13:03:27 -0700433
juliexxiafb45b602019-04-01 12:10:30 -0700434 reporter.removeHandler(failFastHandler);
juliexxiab75e45302019-05-24 07:48:39 -0700435 getConfiguredTarget("//test");
juliexxiafb45b602019-04-01 12:10:30 -0700436 assertContainsEvent(
437 "expected value of type 'string' for " + "//test:cute-animal-fact, but got 24 (int)");
juliexxia22de6cd2019-01-09 07:25:23 -0800438 }
439
juliexxia22de6cd2019-01-09 07:25:23 -0800440 @Test
juliexxia03ff8782019-03-20 13:03:27 -0700441 public void testTransitionOnBuildSetting_noSuchTarget() throws Exception {
juliexxia22de6cd2019-01-09 07:25:23 -0800442 scratch.file(
443 "test/transitions.bzl",
444 "def _transition_impl(settings, attr):",
445 " return {'//test:i-am-not-real': 'imaginary-friend'}",
446 "my_transition = transition(",
447 " implementation = _transition_impl,",
448 " inputs = [],",
449 " outputs = ['//test:i-am-not-real']",
450 ")");
451 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
452
juliexxiafb45b602019-04-01 12:10:30 -0700453 reporter.removeHandler(failFastHandler);
juliexxiab75e45302019-05-24 07:48:39 -0700454 getConfiguredTarget("//test");
juliexxiafb45b602019-04-01 12:10:30 -0700455 assertContainsEvent(
456 "no such target '//test:i-am-not-real': target "
457 + "'i-am-not-real' not declared in package 'test'");
juliexxia03ff8782019-03-20 13:03:27 -0700458 }
459
460 @Test
juliexxiab75e45302019-05-24 07:48:39 -0700461 public void testTransitionOnBuildSetting_noSuchPackage() throws Exception {
juliexxiab75e45302019-05-24 07:48:39 -0700462 scratch.file(
463 "test/transitions.bzl",
464 "def _transition_impl(settings, attr):",
465 " return {'//i-am-not-real': 'imaginary-friend'}",
466 "my_transition = transition(",
467 " implementation = _transition_impl,",
468 " inputs = [],",
469 " outputs = ['//i-am-not-real']",
470 ")");
471 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
472
473 reporter.removeHandler(failFastHandler);
474 getConfiguredTarget("//test");
475 assertContainsEvent("no such package 'i-am-not-real': Unable to find build setting package");
476 }
477
478 @Test
juliexxia03ff8782019-03-20 13:03:27 -0700479 public void testTransitionOnBuildSetting_notABuildSetting() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700480 writeAllowlistFile();
juliexxia03ff8782019-03-20 13:03:27 -0700481 scratch.file(
482 "test/transitions.bzl",
483 "def _transition_impl(settings, attr):",
484 " return {'//test:cute-animal-fact': 'puffins mate for life'}",
485 "my_transition = transition(",
486 " implementation = _transition_impl,",
487 " inputs = [],",
488 " outputs = ['//test:cute-animal-fact']",
489 ")");
490 scratch.file(
491 "test/rules.bzl",
492 "load('//test:transitions.bzl', 'my_transition')",
493 "def _rule_impl(ctx):",
494 " return []",
495 "my_rule = rule(",
496 " implementation = _rule_impl,",
497 " cfg = my_transition,",
498 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700499 " '_allowlist_function_transition': attr.label(",
500 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia03ff8782019-03-20 13:03:27 -0700501 " ),",
502 " },",
503 ")");
504 scratch.file(
505 "test/build_settings.bzl",
506 "def _impl(ctx):",
507 " return []",
508 "non_build_setting = rule(implementation = _impl)");
509 scratch.file(
510 "test/BUILD",
511 "load('//test:rules.bzl', 'my_rule')",
512 "load('//test:build_settings.bzl', 'non_build_setting')",
513 "my_rule(name = 'test')",
514 "non_build_setting(name = 'cute-animal-fact')");
515
juliexxiafb45b602019-04-01 12:10:30 -0700516 reporter.removeHandler(failFastHandler);
517 getConfiguredTarget("//test");
518 assertContainsEvent(
519 "attempting to transition on '//test:cute-animal-fact' which is not a build setting");
juliexxia22de6cd2019-01-09 07:25:23 -0800520 }
521
juliexxia22de6cd2019-01-09 07:25:23 -0800522 @Test
juliexxiadb566782019-04-12 10:48:07 -0700523 public void testTransitionOnBuildSetting_dontStoreDefault() throws Exception {
juliexxiadb566782019-04-12 10:48:07 -0700524 scratch.file(
525 "test/transitions.bzl",
526 "def _transition_impl(settings, attr):",
527 " return {'//test:cute-animal-fact': '" + CUTE_ANIMAL_DEFAULT + "'}",
528 "my_transition = transition(",
529 " implementation = _transition_impl,",
530 " inputs = [],",
531 " outputs = ['//test:cute-animal-fact']",
532 ")");
533 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
534
535 useConfiguration(ImmutableMap.of("//test:cute-animal-fact", "cats can't taste sugar"));
536
537 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
538 assertThat(configuration.getOptions().getStarlarkOptions())
539 .doesNotContainKey(Label.parseAbsoluteUnchecked("//test:cute-animal-fact"));
540 }
541
542 @Test
juliexxia1a70c272019-04-09 09:33:23 -0700543 public void testTransitionReadsBuildSetting_fromDefault() throws Exception {
juliexxia22de6cd2019-01-09 07:25:23 -0800544 scratch.file(
545 "test/transitions.bzl",
546 "def _transition_impl(settings, attr):",
juliexxia1a70c272019-04-09 09:33:23 -0700547 " return {'//test:cute-animal-fact': settings['//test:cute-animal-fact']+' <- TRUE'}",
juliexxia22de6cd2019-01-09 07:25:23 -0800548 "my_transition = transition(",
549 " implementation = _transition_impl,",
550 " inputs = ['//test:cute-animal-fact'],",
juliexxia1a70c272019-04-09 09:33:23 -0700551 " outputs = ['//test:cute-animal-fact']",
552 ")");
553 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
554
555 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
556 assertThat(
557 configuration
558 .getOptions()
559 .getStarlarkOptions()
560 .get(Label.parseAbsoluteUnchecked("//test:cute-animal-fact")))
561 .isEqualTo("cows produce more milk when they listen to soothing music <- TRUE");
562 }
563
564 @Test
565 public void testTransitionReadsBuildSetting_fromCommandLine() throws Exception {
juliexxia1a70c272019-04-09 09:33:23 -0700566 scratch.file(
567 "test/transitions.bzl",
568 "def _transition_impl(settings, attr):",
569 " return {'//test:cute-animal-fact': settings['//test:cute-animal-fact']+' <- TRUE'}",
570 "my_transition = transition(",
571 " implementation = _transition_impl,",
572 " inputs = ['//test:cute-animal-fact'],",
573 " outputs = ['//test:cute-animal-fact']",
574 ")");
575 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
576
577 useConfiguration(ImmutableMap.of("//test:cute-animal-fact", "rats are ticklish"));
578
579 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
580 assertThat(
581 configuration
582 .getOptions()
583 .getStarlarkOptions()
584 .get(Label.parseAbsoluteUnchecked("//test:cute-animal-fact")))
585 .isEqualTo("rats are ticklish <- TRUE");
586 }
587
588 @Test
589 public void testTransitionReadsBuildSetting_notABuildSetting() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700590 writeAllowlistFile();
juliexxia1a70c272019-04-09 09:33:23 -0700591 scratch.file(
592 "test/transitions.bzl",
593 "def _transition_impl(settings, attr):",
594 " return {'//test:cute-animal-fact': 'puffins mate for life'}",
595 "my_transition = transition(",
596 " implementation = _transition_impl,",
597 " inputs = ['//test:cute-animal-fact'],",
598 " outputs = ['//test:cute-animal-fact']",
599 ")");
600 scratch.file(
601 "test/rules.bzl",
602 "load('//test:transitions.bzl', 'my_transition')",
603 "def _rule_impl(ctx):",
604 " return []",
605 "my_rule = rule(",
606 " implementation = _rule_impl,",
607 " cfg = my_transition,",
608 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700609 " '_allowlist_function_transition': attr.label(",
610 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia1a70c272019-04-09 09:33:23 -0700611 " ),",
612 " },",
613 ")");
614 scratch.file(
615 "test/build_settings.bzl",
616 "def _impl(ctx):",
617 " return []",
618 "non_build_setting = rule(implementation = _impl)");
619 scratch.file(
620 "test/BUILD",
621 "load('//test:rules.bzl', 'my_rule')",
622 "load('//test:build_settings.bzl', 'non_build_setting')",
623 "my_rule(name = 'test')",
624 "non_build_setting(name = 'cute-animal-fact')");
625
626 reporter.removeHandler(failFastHandler);
627 getConfiguredTarget("//test");
628 assertContainsEvent(
629 "attempting to transition on '//test:cute-animal-fact' which is not a build setting");
630 }
631
632 @Test
633 public void testTransitionReadsBuildSetting_noSuchTarget() throws Exception {
juliexxia1a70c272019-04-09 09:33:23 -0700634 scratch.file(
635 "test/transitions.bzl",
636 "def _transition_impl(settings, attr):",
637 " return {'//test:cute-animal-fact': settings['//test:cute-animal-fact']+' <- TRUE'}",
638 "my_transition = transition(",
639 " implementation = _transition_impl,",
640 " inputs = ['//test:i-am-not-real'],",
641 " outputs = ['//test:cute-animal-fact']",
juliexxia22de6cd2019-01-09 07:25:23 -0800642 ")");
643 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
644
juliexxia03ff8782019-03-20 13:03:27 -0700645 reporter.removeHandler(failFastHandler);
juliexxiafb45b602019-04-01 12:10:30 -0700646 getConfiguredTarget("//test");
juliexxia03ff8782019-03-20 13:03:27 -0700647 assertContainsEvent(
juliexxia1a70c272019-04-09 09:33:23 -0700648 "no such target '//test:i-am-not-real': target "
649 + "'i-am-not-real' not declared in package 'test'");
juliexxia922312f2019-03-12 08:44:33 -0700650 }
juliexxia1a568242019-02-15 09:16:46 -0800651
652 @Test
juliexxiab63a4a92019-06-14 12:05:18 -0700653 public void testAliasedBuildSetting() throws Exception {
juliexxiab63a4a92019-06-14 12:05:18 -0700654 scratch.file(
655 "test/transitions.bzl",
656 "def _transition_impl(settings, attr):",
657 " return {'//test:fact': 'puffins mate for life'}",
658 "my_transition = transition(",
659 " implementation = _transition_impl,",
660 " inputs = [],",
661 " outputs = ['//test:fact']",
662 ")");
663 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
664 scratch.overwriteFile(
665 "test/BUILD",
666 "load('//test:rules.bzl', 'my_rule')",
667 "load('//test:build_settings.bzl', 'string_flag')",
668 "my_rule(name = 'test')",
669 "alias(name = 'fact', actual = ':cute-animal-fact')",
670 "string_flag(",
671 " name = 'cute-animal-fact',",
672 " build_setting_default = '" + CUTE_ANIMAL_DEFAULT + "',",
673 ")");
674
675 useConfiguration(ImmutableMap.of("//test:cute-animal-fact", "rats are ticklish"));
676
677 ImmutableMap<Label, Object> starlarkOptions =
678 getConfiguration(getConfiguredTarget("//test")).getOptions().getStarlarkOptions();
679 assertThat(starlarkOptions.get(Label.parseAbsoluteUnchecked("//test:cute-animal-fact")))
680 .isEqualTo("puffins mate for life");
681 assertThat(starlarkOptions).doesNotContainKey(Label.parseAbsoluteUnchecked("//test:fact"));
682 assertThat(starlarkOptions.keySet())
683 .containsExactly(Label.parseAbsoluteUnchecked("//test:cute-animal-fact"));
684 }
685
686 @Test
687 public void testAliasedBuildSetting_chainedAliases() throws Exception {
juliexxiab63a4a92019-06-14 12:05:18 -0700688 scratch.file(
689 "test/transitions.bzl",
690 "def _transition_impl(settings, attr):",
691 " return {'//test:fact': 'puffins mate for life'}",
692 "my_transition = transition(",
693 " implementation = _transition_impl,",
694 " inputs = [],",
695 " outputs = ['//test:fact']",
696 ")");
697 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
698 scratch.overwriteFile(
699 "test/BUILD",
700 "load('//test:rules.bzl', 'my_rule')",
701 "load('//test:build_settings.bzl', 'string_flag')",
702 "my_rule(name = 'test')",
703 "alias(name = 'fact', actual = ':alias2')",
704 "alias(name = 'alias2', actual = ':cute-animal-fact')",
705 "string_flag(",
706 " name = 'cute-animal-fact',",
707 " build_setting_default = '" + CUTE_ANIMAL_DEFAULT + "',",
708 ")");
709
710 useConfiguration(ImmutableMap.of("//test:cute-animal-fact", "rats are ticklish"));
711
712 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
713 assertThat(
714 configuration
715 .getOptions()
716 .getStarlarkOptions()
717 .get(Label.parseAbsoluteUnchecked("//test:cute-animal-fact")))
718 .isEqualTo("puffins mate for life");
719 }
720
721 @Test
722 public void testAliasedBuildSetting_configuredActualValue() throws Exception {
juliexxiab63a4a92019-06-14 12:05:18 -0700723 scratch.file(
724 "test/transitions.bzl",
725 "def _transition_impl(settings, attr):",
726 " return {'//test:fact': 'puffins mate for life'}",
727 "my_transition = transition(",
728 " implementation = _transition_impl,",
729 " inputs = [],",
730 " outputs = ['//test:fact']",
731 ")");
732 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
733 scratch.overwriteFile(
734 "test/BUILD",
735 "load('//test:rules.bzl', 'my_rule')",
736 "load('//test:build_settings.bzl', 'string_flag')",
737 "my_rule(name = 'test')",
738 "alias(",
739 " name = 'fact',",
740 " actual = select({",
741 " '//conditions:default': ':cute-animal-fact',",
742 " ':true-config': 'other-cute-animal-fact',",
743 " })",
744 ")",
745 "config_setting(",
746 " name = 'true-config',",
twigg4970e0f2021-03-31 15:34:49 -0700747 " values = {'foo': 'true'},",
juliexxiab63a4a92019-06-14 12:05:18 -0700748 ")",
749 "string_flag(",
750 " name = 'cute-animal-fact',",
751 " build_setting_default = '" + CUTE_ANIMAL_DEFAULT + "',",
752 ")",
753 "string_flag(",
754 " name = 'other-cute-animal-fact',",
755 " build_setting_default = '" + CUTE_ANIMAL_DEFAULT + "',",
756 ")");
757
758 reporter.removeHandler(failFastHandler);
759 getConfiguredTarget("//test");
760 assertContainsEvent(
761 "attempting to transition on aliased build setting '//test:fact', the actual value of"
762 + " which uses select().");
763 }
764
765 @Test
766 public void testAliasedBuildSetting_cyclicalAliases() throws Exception {
juliexxiab63a4a92019-06-14 12:05:18 -0700767 scratch.file(
768 "test/transitions.bzl",
769 "def _transition_impl(settings, attr):",
770 " return {'//test:alias1': 'puffins mate for life'}",
771 "my_transition = transition(",
772 " implementation = _transition_impl,",
773 " inputs = [],",
774 " outputs = ['//test:alias1']",
775 ")");
776 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
777 scratch.overwriteFile(
778 "test/BUILD",
779 "load('//test:rules.bzl', 'my_rule')",
780 "load('//test:build_settings.bzl', 'string_flag')",
781 "my_rule(name = 'test')",
782 "alias(name = 'alias1', actual = ':alias2')",
783 "alias(name = 'alias2', actual = ':alias1')");
784
785 reporter.removeHandler(failFastHandler);
786 getConfiguredTarget("//test");
787 assertContainsEvent("Error with aliased build settings related to '//test:alias1'.");
788 }
789
790 @Test
791 public void testAliasedBuildSetting_setAliasAndActual() throws Exception {
juliexxiab63a4a92019-06-14 12:05:18 -0700792 scratch.file(
793 "test/transitions.bzl",
794 "def _transition_impl(settings, attr):",
795 " return {",
796 " '//test:alias': 'puffins mate for life',",
797 " '//test:actual': 'cats cannot taste sugar',",
798 "}",
799 "my_transition = transition(",
800 " implementation = _transition_impl,",
801 " inputs = [],",
802 " outputs = [",
803 " '//test:alias',",
804 " '//test:actual',",
805 " ]",
806 ")");
807 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
808 scratch.overwriteFile(
809 "test/BUILD",
810 "load('//test:rules.bzl', 'my_rule')",
811 "load('//test:build_settings.bzl', 'string_flag')",
812 "my_rule(name = 'test')",
813 "alias(name = 'alias', actual = ':actual')",
814 "string_flag(",
815 " name = 'actual',",
816 " build_setting_default = '" + CUTE_ANIMAL_DEFAULT + "',",
817 ")");
818
819 reporter.removeHandler(failFastHandler);
820 getConfiguredTarget("//test");
821 assertContainsEvent("Error with aliased build settings related to '//test:actual'.");
822 }
823
824 @Test
825 public void testAliasedBuildSetting_outputReturnMismatch() throws Exception {
juliexxiab63a4a92019-06-14 12:05:18 -0700826 scratch.file(
827 "test/transitions.bzl",
828 "def _transition_impl(settings, attr):",
829 " return {",
830 " '//test:actual': 'cats cannot taste sugar',",
831 "}",
832 "my_transition = transition(",
833 " implementation = _transition_impl,",
834 " inputs = [],",
835 " outputs = [",
836 " '//test:alias',",
837 " ]",
838 ")");
839 writeRulesBuildSettingsAndBUILDforBuildSettingTransitionTests();
840 scratch.overwriteFile(
841 "test/BUILD",
842 "load('//test:rules.bzl', 'my_rule')",
843 "load('//test:build_settings.bzl', 'string_flag')",
844 "my_rule(name = 'test')",
845 "alias(name = 'alias', actual = ':actual')",
846 "string_flag(",
847 " name = 'actual',",
848 " build_setting_default = '" + CUTE_ANIMAL_DEFAULT + "',",
849 ")");
850
851 reporter.removeHandler(failFastHandler);
852 getConfiguredTarget("//test");
853 assertContainsEvent("transition function returned undeclared output '//test:actual'");
854 }
855
856 @Test
juliexxia1a568242019-02-15 09:16:46 -0800857 public void testOneParamTransitionFunctionApiFails() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700858 writeAllowlistFile();
juliexxia1a568242019-02-15 09:16:46 -0800859 scratch.file(
860 "test/transitions.bzl",
861 "def _impl(settings):",
twigg4970e0f2021-03-31 15:34:49 -0700862 " return {'//command_line_option:foo': 'post-transition'}",
juliexxia1a568242019-02-15 09:16:46 -0800863 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -0700864 " outputs = ['//command_line_option:foo'])");
juliexxia1a568242019-02-15 09:16:46 -0800865 scratch.file(
866 "test/rules.bzl",
867 "load('//test:transitions.bzl', 'my_transition')",
868 "def _impl(ctx):",
869 " return []",
juliexxia30976d82019-03-12 10:59:26 -0700870 "my_rule = rule(",
871 " implementation = _impl,",
872 " cfg = my_transition,",
873 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700874 " '_allowlist_function_transition': attr.label(",
875 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700876 " ),",
877 " },",
878 ")");
juliexxia1a568242019-02-15 09:16:46 -0800879 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
880
juliexxia03ff8782019-03-20 13:03:27 -0700881 reporter.removeHandler(failFastHandler);
juliexxiafb45b602019-04-01 12:10:30 -0700882 getConfiguredTarget("//test");
adonovan40446b82020-04-22 06:59:42 -0700883 assertContainsEvent("_impl() accepts no more than 1 positional argument but got 2");
juliexxia1a568242019-02-15 09:16:46 -0800884 }
juliexxiaff93b192019-02-19 08:02:19 -0800885
886 @Test
887 public void testCannotTransitionOnExperimentalFlag() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700888 writeAllowlistFile();
juliexxiaff93b192019-02-19 08:02:19 -0800889 scratch.file(
890 "test/transitions.bzl",
891 "def _impl(settings, attr):",
juliexxiad17649a2020-05-26 10:48:04 -0700892 " return {'//command_line_option:experimental_something_something': True}",
juliexxiaff93b192019-02-19 08:02:19 -0800893 "my_transition = transition(implementation = _impl, inputs = [],",
juliexxiad17649a2020-05-26 10:48:04 -0700894 " outputs = ['//command_line_option:experimental_something_something'])");
juliexxiaff93b192019-02-19 08:02:19 -0800895 scratch.file(
896 "test/rules.bzl",
897 "load('//test:transitions.bzl', 'my_transition')",
898 "def _impl(ctx):",
899 " return []",
juliexxia30976d82019-03-12 10:59:26 -0700900 "my_rule = rule(",
901 " implementation = _impl,",
902 " cfg = my_transition,",
903 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700904 " '_allowlist_function_transition': attr.label(",
905 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700906 " ),",
907 " },",
908 ")");
juliexxiaff93b192019-02-19 08:02:19 -0800909 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
910
911 reporter.removeHandler(failFastHandler);
912 getConfiguredTarget("//test");
913 assertContainsEvent("Cannot transition on --experimental_* or --incompatible_* options");
914 }
juliexxia30976d82019-03-12 10:59:26 -0700915
916 @Test
aiuto50226ac2020-06-14 21:28:27 -0700917 public void testCannotTransitionWithoutAllowlist() throws Exception {
juliexxia30976d82019-03-12 10:59:26 -0700918 scratch.file(
cushon1812caf2020-06-24 10:54:19 -0700919 "tools/allowlists/function_transition_allowlist/BUILD",
juliexxia30976d82019-03-12 10:59:26 -0700920 "package_group(",
cushon1812caf2020-06-24 10:54:19 -0700921 " name = 'function_transition_allowlist',",
juliexxia30976d82019-03-12 10:59:26 -0700922 " packages = [],",
923 ")");
924 scratch.file(
925 "test/transitions.bzl",
926 "def _impl(settings, attr):",
twigg4970e0f2021-03-31 15:34:49 -0700927 " return {'//command_line_option:foo': 'post-transition'}",
juliexxia30976d82019-03-12 10:59:26 -0700928 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -0700929 " outputs = ['//command_line_option:foo'])");
juliexxia30976d82019-03-12 10:59:26 -0700930 scratch.file(
931 "test/rules.bzl",
932 "load('//test:transitions.bzl', 'my_transition')",
933 "def _impl(ctx):",
934 " return []",
935 "my_rule = rule(",
936 " implementation = _impl,",
937 " cfg = my_transition,",
938 ")");
939 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
940
twigg4970e0f2021-03-31 15:34:49 -0700941 useConfiguration("--foo=pre-transition");
juliexxia30976d82019-03-12 10:59:26 -0700942
943 reporter.removeHandler(failFastHandler);
944 getConfiguredTarget("//test");
aiuto50226ac2020-06-14 21:28:27 -0700945 assertContainsEvent("Use of Starlark transition without allowlist");
juliexxia30976d82019-03-12 10:59:26 -0700946 }
juliexxiac33f0c82019-03-25 16:37:41 -0700947
948 @Test
949 public void testNoNullOptionValues() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -0700950 writeAllowlistFile();
juliexxiac33f0c82019-03-25 16:37:41 -0700951 scratch.file(
952 "test/transitions.bzl",
953 "def _impl(settings, attr):",
juliexxia6778a052019-04-09 08:25:05 -0700954 " if settings['//command_line_option:nullable_option'] == None:",
twigg4970e0f2021-03-31 15:34:49 -0700955 " return {'//command_line_option:foo': 'post-transition'}",
juliexxiac33f0c82019-03-25 16:37:41 -0700956 " else:",
twigg4970e0f2021-03-31 15:34:49 -0700957 " return {'//command_line_option:foo': settings['//command_line_option:foo']}",
juliexxiac33f0c82019-03-25 16:37:41 -0700958 "my_transition = transition(implementation = _impl,",
959 " inputs = [",
twigg4970e0f2021-03-31 15:34:49 -0700960 " '//command_line_option:foo',",
juliexxia6778a052019-04-09 08:25:05 -0700961 " '//command_line_option:nullable_option'",
juliexxiac33f0c82019-03-25 16:37:41 -0700962 " ],",
twigg4970e0f2021-03-31 15:34:49 -0700963 " outputs = ['//command_line_option:foo'])");
juliexxiac33f0c82019-03-25 16:37:41 -0700964 scratch.file(
965 "test/rules.bzl",
966 "load('//test:transitions.bzl', 'my_transition')",
967 "def _impl(ctx):",
968 " return []",
969 "my_rule = rule(",
970 " implementation = _impl,",
971 " cfg = my_transition,",
972 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -0700973 " '_allowlist_function_transition': attr.label(",
974 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxiac33f0c82019-03-25 16:37:41 -0700975 " ),",
976 " })");
977 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
978
twigg4970e0f2021-03-31 15:34:49 -0700979 useConfiguration("--nullable_option=", "--foo=pre-transition");
juliexxiac33f0c82019-03-25 16:37:41 -0700980
981 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
twigg4970e0f2021-03-31 15:34:49 -0700982 assertThat(configuration.getOptions().get(DummyTestOptions.class).foo)
983 .isEqualTo("post-transition");
juliexxiac33f0c82019-03-25 16:37:41 -0700984 }
juliexxiad21fa422019-03-28 09:59:26 -0700985
986 @Test
aiuto50226ac2020-06-14 21:28:27 -0700987 public void testAllowlistOnRuleNotTargets() throws Exception {
988 // allowlists //test/...
989 writeAllowlistFile();
juliexxiad21fa422019-03-28 09:59:26 -0700990 scratch.file(
991 "test/transitions.bzl",
992 "def _impl(settings, attr):",
twigg4970e0f2021-03-31 15:34:49 -0700993 " return {'//command_line_option:foo': 'post-transition'}",
juliexxiad21fa422019-03-28 09:59:26 -0700994 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -0700995 " outputs = ['//command_line_option:foo'])");
juliexxiad21fa422019-03-28 09:59:26 -0700996 scratch.file(
997 "test/rules.bzl",
998 "load('//test:transitions.bzl', 'my_transition')",
999 "def _impl(ctx):",
1000 " return []",
1001 "my_rule = rule(",
1002 " implementation = _impl,",
1003 " cfg = my_transition,",
1004 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -07001005 " '_allowlist_function_transition': attr.label(",
1006 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxiad21fa422019-03-28 09:59:26 -07001007 " ),",
1008 " })");
1009 scratch.file(
1010 "neverland/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
1011 scratch.file("test/BUILD");
twigg4970e0f2021-03-31 15:34:49 -07001012 useConfiguration("--foo=pre-transition");
juliexxiad21fa422019-03-28 09:59:26 -07001013
1014 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//neverland:test"));
twigg4970e0f2021-03-31 15:34:49 -07001015 assertThat(configuration.getOptions().get(DummyTestOptions.class).foo)
1016 .isEqualTo("post-transition");
juliexxiad21fa422019-03-28 09:59:26 -07001017 }
1018
Googlerfe8275d2021-02-05 16:36:38 -08001019 // TODO(blaze-configurability): We probably want to eventually turn this off. Flip this test when
1020 // this isn't allowed anymore.
juliexxiad21fa422019-03-28 09:59:26 -07001021 @Test
aiuto50226ac2020-06-14 21:28:27 -07001022 public void testAllowlistOnTargetsStillWorks() throws Exception {
1023 // allowlists //test/...
1024 writeAllowlistFile();
juliexxiad21fa422019-03-28 09:59:26 -07001025 scratch.file(
1026 "neverland/transitions.bzl",
1027 "def _impl(settings, attr):",
twigg4970e0f2021-03-31 15:34:49 -07001028 " return {'//command_line_option:foo': 'post-transition'}",
juliexxiad21fa422019-03-28 09:59:26 -07001029 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -07001030 " outputs = ['//command_line_option:foo'])");
juliexxiad21fa422019-03-28 09:59:26 -07001031 scratch.file(
1032 "neverland/rules.bzl",
1033 "load('//neverland:transitions.bzl', 'my_transition')",
1034 "def _impl(ctx):",
1035 " return []",
1036 "my_rule = rule(",
1037 " implementation = _impl,",
1038 " cfg = my_transition,",
1039 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -07001040 " '_allowlist_function_transition': attr.label(",
1041 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxiad21fa422019-03-28 09:59:26 -07001042 " ),",
1043 " })");
1044 scratch.file(
1045 "test/BUILD", "load('//neverland:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
1046 scratch.file("neverland/BUILD");
twigg4970e0f2021-03-31 15:34:49 -07001047 useConfiguration("--foo=pre-transition");
juliexxiad21fa422019-03-28 09:59:26 -07001048
1049 BuildConfiguration configuration = getConfiguration(getConfiguredTarget("//test"));
twigg4970e0f2021-03-31 15:34:49 -07001050 assertThat(configuration.getOptions().get(DummyTestOptions.class).foo)
1051 .isEqualTo("post-transition");
juliexxiad21fa422019-03-28 09:59:26 -07001052 }
juliexxiabdc6c102019-05-20 11:58:02 -07001053
1054 /**
1055 * Regression test to ensure that an empty dict is not interpreted as a dict of dicts and
1056 * generates the proper error message.
1057 */
1058 @Test
1059 public void testEmptyReturnDict() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -07001060 writeAllowlistFile();
juliexxiabdc6c102019-05-20 11:58:02 -07001061 scratch.file(
1062 "test/transitions.bzl",
1063 "def _impl(settings, attr):",
1064 " return {}",
1065 "my_transition = transition(implementation = _impl, inputs = [],",
twigg4970e0f2021-03-31 15:34:49 -07001066 " outputs = ['//command_line_option:foo'])");
juliexxiabdc6c102019-05-20 11:58:02 -07001067 scratch.file(
1068 "test/rules.bzl",
1069 "load('//test:transitions.bzl', 'my_transition')",
1070 "def _impl(ctx):",
1071 " return []",
1072 "my_rule = rule(",
1073 " implementation = _impl,",
1074 " cfg = my_transition,",
1075 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -07001076 " '_allowlist_function_transition': attr.label(",
1077 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxiabdc6c102019-05-20 11:58:02 -07001078 " ),",
1079 " })");
1080 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
1081
1082 reporter.removeHandler(failFastHandler);
1083 getConfiguredTarget("//test");
1084 assertContainsEvent(
twigg4970e0f2021-03-31 15:34:49 -07001085 "transition outputs [//command_line_option:foo] were "
juliexxiabdc6c102019-05-20 11:58:02 -07001086 + "not defined by transition function");
1087 }
gregcef0a40ac2020-03-31 14:11:30 -07001088
1089 @Test
1090 public void composingTransitionReportsAllStarlarkErrors() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -07001091 writeAllowlistFile();
gregcef0a40ac2020-03-31 14:11:30 -07001092 scratch.file(
1093 "test/build_settings.bzl",
1094 "def _impl(ctx):",
1095 " return []",
1096 "string_flag = rule(implementation = _impl, build_setting = config.string(flag=True))");
1097 scratch.file(
1098 "test/transitions.bzl",
1099 "def _impl(settings, attr):",
1100 " return {}",
1101 "attr_transition = transition(implementation = _impl, inputs = [],",
1102 " outputs = ['//test:attr_transition_output_flag'])",
1103 "self_transition = transition(implementation = _impl, inputs = [],",
1104 " outputs = ['//test:self_transition_output_flag'])");
1105 scratch.file(
1106 "test/rules.bzl",
1107 "load('//test:transitions.bzl', 'attr_transition', 'self_transition')",
1108 "def _impl(ctx):",
1109 " return []",
1110 "rule_with_attr_transition = rule(",
1111 " implementation = _impl,",
1112 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -07001113 " '_allowlist_function_transition': attr.label(",
1114 " default = '//tools/allowlists/function_transition_allowlist'),",
gregcef0a40ac2020-03-31 14:11:30 -07001115 " 'deps': attr.label_list(cfg = attr_transition),",
1116 " })",
1117 "rule_with_self_transition = rule(",
1118 " implementation = _impl,",
1119 " cfg = self_transition,",
1120 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -07001121 " '_allowlist_function_transition': attr.label(",
1122 " default = '//tools/allowlists/function_transition_allowlist'),",
gregcef0a40ac2020-03-31 14:11:30 -07001123 " })");
1124 scratch.file(
1125 "test/BUILD",
1126 "load('//test:rules.bzl', 'rule_with_attr_transition', 'rule_with_self_transition')",
1127 "load('//test:build_settings.bzl', 'string_flag')",
1128 "string_flag(name = 'attr_transition_output_flag', build_setting_default='')",
1129 "string_flag(name = 'self_transition_output_flag', build_setting_default='')",
1130 "rule_with_attr_transition(name = 'buildme', deps = [':adep'])",
1131 "rule_with_self_transition(name = 'adep')");
1132
1133 reporter.removeHandler(failFastHandler);
1134 getConfiguredTarget("//test:buildme");
1135 assertContainsEvent(
1136 "transition outputs [//test:attr_transition_output_flag] were not defined by transition "
1137 + "function");
1138 assertContainsEvent(
1139 "transition outputs [//test:self_transition_output_flag] were not defined by transition "
1140 + "function");
1141 }
juliexxiabf57d6b2020-04-14 07:36:59 -07001142
1143 @Test
1144 public void testTransitionOnDefine() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -07001145 writeAllowlistFile();
juliexxiabf57d6b2020-04-14 07:36:59 -07001146 scratch.file(
1147 "test/transitions.bzl",
1148 "def _impl(settings, attr):",
1149 " return {'//command_line_option:define': 'chonky=true'}",
1150 "my_transition = transition(implementation = _impl, inputs = [],",
1151 " outputs = ['//command_line_option:define'])");
1152 scratch.file(
1153 "test/rules.bzl",
1154 "load('//test:transitions.bzl', 'my_transition')",
1155 "def _impl(ctx):",
1156 " return []",
1157 "my_rule = rule(",
1158 " implementation = _impl,",
1159 " cfg = my_transition,",
1160 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -07001161 " '_allowlist_function_transition': attr.label(",
1162 " default = '//tools/allowlists/function_transition_allowlist',",
juliexxiabf57d6b2020-04-14 07:36:59 -07001163 " ),",
1164 " })");
1165 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
1166
1167 reporter.removeHandler(failFastHandler);
1168 getConfiguredTarget("//test");
1169 assertContainsEvent("Starlark transition on --define not supported - try using build settings");
1170 }
gregce7fc9ae72020-04-24 10:54:14 -07001171
1172 @Test
1173 public void successfulTypeConversionOfNativeListOption() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -07001174 writeAllowlistFile();
gregce7fc9ae72020-04-24 10:54:14 -07001175 scratch.file(
1176 "test/transitions.bzl",
1177 "def _impl(settings, attr):",
1178 " return {'//command_line_option:platforms': ['//test:my_platform']}",
1179 "my_transition = transition(implementation = _impl, inputs = [],",
1180 " outputs = ['//command_line_option:platforms'])");
1181 scratch.file(
1182 "test/rules.bzl",
1183 "load('//test:transitions.bzl', 'my_transition')",
1184 "def _impl(ctx):",
1185 " return []",
1186 "my_rule = rule(",
1187 " implementation = _impl,",
1188 " cfg = my_transition,",
1189 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -07001190 " '_allowlist_function_transition': attr.label(",
1191 " default = '//tools/allowlists/function_transition_allowlist',",
gregce7fc9ae72020-04-24 10:54:14 -07001192 " ),",
1193 " })");
1194 scratch.file(
1195 "test/BUILD",
1196 "load('//test:rules.bzl', 'my_rule')",
1197 "platform(name = 'my_platform')",
1198 "my_rule(name = 'test')");
1199
1200 getConfiguredTarget("//test");
1201 assertNoEvents();
1202 }
1203
juliexxia1cf37462020-10-20 14:48:10 -07001204 // Regression test for b/170729565
1205 @Test
1206 public void testSetBooleanNativeOptionWithStarlarkBoolean() throws Exception {
1207 writeAllowlistFile();
1208 scratch.file(
1209 "test/transitions.bzl",
1210 "def _impl(settings, attr):",
1211 " return {'//command_line_option:bool': True}",
1212 "my_transition = transition(implementation = _impl, inputs = [],",
1213 " outputs = ['//command_line_option:bool'])");
1214 scratch.file(
1215 "test/rules.bzl",
1216 "load('//test:transitions.bzl', 'my_transition')",
1217 "def _impl(ctx):",
1218 " return []",
1219 "my_rule = rule(",
1220 " implementation = _impl,",
1221 " cfg = my_transition,",
1222 " attrs = {",
1223 " '_allowlist_function_transition': attr.label(",
1224 " default = '//tools/allowlists/function_transition_allowlist',",
1225 " ),",
1226 " })");
1227 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
1228 useConfiguration("--bool=false");
1229 ConfiguredTarget ct = getConfiguredTarget("//test");
1230 assertNoEvents();
1231 assertThat(getConfiguration(ct).getOptions().get(DummyTestOptions.class).bool).isTrue();
1232 }
1233
1234 // Regression test for b/170729565
1235 @Test
1236 public void testSetBooleanNativeOptionWithItself() throws Exception {
1237 writeAllowlistFile();
1238 scratch.file(
1239 "test/transitions.bzl",
1240 "def _impl(settings, attr):",
1241 " return {'//command_line_option:bool': settings['//command_line_option:bool']}",
1242 "my_transition = transition(implementation = _impl,",
1243 " inputs = ['//command_line_option:bool'],",
1244 " outputs = ['//command_line_option:bool'])");
1245 scratch.file(
1246 "test/rules.bzl",
1247 "load('//test:transitions.bzl', 'my_transition')",
1248 "def _impl(ctx):",
1249 " return []",
1250 "my_rule = rule(",
1251 " implementation = _impl,",
1252 " cfg = my_transition,",
1253 " attrs = {",
1254 " '_allowlist_function_transition': attr.label(",
1255 " default = '//tools/allowlists/function_transition_allowlist',",
1256 " ),",
1257 " })");
1258 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
1259 useConfiguration("--bool=false");
1260 ConfiguredTarget ct = getConfiguredTarget("//test");
1261 assertNoEvents();
1262 assertThat(getConfiguration(ct).getOptions().get(DummyTestOptions.class).bool).isFalse();
1263 }
1264
gregce7fc9ae72020-04-24 10:54:14 -07001265 @Test
1266 public void failedTypeConversionOfNativeListOption() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -07001267 writeAllowlistFile();
gregce7fc9ae72020-04-24 10:54:14 -07001268 scratch.file(
1269 "test/transitions.bzl",
1270 "def _impl(settings, attr):",
1271 " return {'//command_line_option:platforms': ['this is not a valid label::']}",
1272 "my_transition = transition(implementation = _impl, inputs = [],",
1273 " outputs = ['//command_line_option:platforms'])");
1274 scratch.file(
1275 "test/rules.bzl",
1276 "load('//test:transitions.bzl', 'my_transition')",
1277 "def _impl(ctx):",
1278 " return []",
1279 "my_rule = rule(",
1280 " implementation = _impl,",
1281 " cfg = my_transition,",
1282 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -07001283 " '_allowlist_function_transition': attr.label(",
1284 " default = '//tools/allowlists/function_transition_allowlist',",
gregce7fc9ae72020-04-24 10:54:14 -07001285 " ),",
1286 " })");
1287 scratch.file(
1288 "test/BUILD",
1289 "load('//test:rules.bzl', 'my_rule')",
1290 "platform(name = 'my_platform')",
1291 "my_rule(name = 'test')");
1292
1293 reporter.removeHandler(failFastHandler);
1294 getConfiguredTarget("//test");
1295 assertContainsEvent("invalid target name ':': target names may not contain ':'");
1296 }
1297
1298 @Test
1299 public void successfulTypeConversionOfNativeListOptionEmptyList() throws Exception {
aiuto50226ac2020-06-14 21:28:27 -07001300 writeAllowlistFile();
gregce7fc9ae72020-04-24 10:54:14 -07001301 scratch.file(
1302 "test/transitions.bzl",
1303 "def _impl(settings, attr):",
1304 " return {'//command_line_option:fission': []}",
1305 "my_transition = transition(implementation = _impl, inputs = [],",
1306 " outputs = ['//command_line_option:fission'])");
1307 scratch.file(
1308 "test/rules.bzl",
1309 "load('//test:transitions.bzl', 'my_transition')",
1310 "def _impl(ctx):",
1311 " return []",
1312 "my_rule = rule(",
1313 " implementation = _impl,",
1314 " cfg = my_transition,",
1315 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -07001316 " '_allowlist_function_transition': attr.label(",
1317 " default = '//tools/allowlists/function_transition_allowlist',",
gregce7fc9ae72020-04-24 10:54:14 -07001318 " ),",
1319 " })");
1320 scratch.file(
1321 "test/BUILD",
1322 "load('//test:rules.bzl', 'my_rule')",
1323 "platform(name = 'my_platform')",
1324 "my_rule(name = 'test')");
1325
1326 ConfiguredTarget ct = getConfiguredTarget("//test");
1327 assertNoEvents();
1328 assertThat(getConfiguration(ct).getOptions().get(CppOptions.class).fissionModes).isEmpty();
1329 }
gregce06b76c92020-06-19 14:46:56 -07001330
1331 @Test
1332 public void starlarkPatchTransitionRequiredFragments() throws Exception {
1333 // All Starlark rule transitions are patch transitions, while all Starlark attribute transitions
1334 // are split transitions.
1335 writeAllowlistFile();
1336 scratch.file(
1337 "test/transitions.bzl",
1338 "def _impl(settings, attr):",
1339 " return {'//command_line_option:copt': []}", // --copt is a C++ option.
1340 "my_transition = transition(implementation = _impl, inputs = [],",
1341 " outputs = ['//command_line_option:copt'])");
1342 scratch.file(
1343 "test/rules.bzl",
1344 "load('//test:transitions.bzl', 'my_transition')",
1345 "def _impl(ctx):",
1346 " return []",
1347 "my_rule = rule(",
1348 " implementation = _impl,",
1349 " cfg = my_transition,",
1350 " attrs = {",
cushon1812caf2020-06-24 10:54:19 -07001351 " '_allowlist_function_transition': attr.label(",
1352 " default = '//tools/allowlists/function_transition_allowlist',",
gregce06b76c92020-06-19 14:46:56 -07001353 " ),",
1354 " })");
1355 scratch.file(
1356 "test/BUILD",
1357 "load('//test:rules.bzl', 'my_rule')",
1358 "platform(name = 'my_platform')",
1359 "my_rule(name = 'test')");
1360
1361 ConfiguredTargetAndData ct = getConfiguredTargetAndData("//test");
1362 assertNoEvents();
1363 Rule testTarget = (Rule) ct.getTarget();
1364 ConfigurationTransition ruleTransition =
1365 testTarget.getRuleClassObject().getTransitionFactory().create(testTarget);
1366 assertThat(ruleTransition.requiresOptionFragments(ct.getConfiguration().getOptions()))
gregce24e09f72020-07-01 15:18:36 -07001367 .containsExactly("CppOptions");
gregce06b76c92020-06-19 14:46:56 -07001368 }
janakrca6209f2020-11-13 19:17:27 -08001369
1370 /**
1371 * Unit test for an invalid output directory from a mnemonic via a dep transition. Integration
1372 * test for top-level transition in //src/test/shell/integration:starlark_configurations_test#
1373 * test_invalid_mnemonic_from_transition_top_level. Has to be an integration test because the
1374 * error is emitted in BuildTool.
1375 */
1376 @Test
1377 public void invalidMnemonicFromDepTransition() throws Exception {
1378 writeAllowlistFile();
1379 scratch.file(
1380 "test/transitions.bzl",
1381 "def _impl(settings, attr):",
1382 " return {'//command_line_option:cpu': '//bad:cpu'}",
1383 "my_transition = transition(implementation = _impl, inputs = [],",
1384 " outputs = ['//command_line_option:cpu'])");
1385 scratch.file(
1386 "test/rules.bzl",
1387 "load('//test:transitions.bzl', 'my_transition')",
1388 "def _impl(ctx):",
1389 " return []",
1390 "my_rule = rule(",
1391 " implementation = _impl,",
1392 " cfg = my_transition,",
1393 " attrs = {",
1394 " '_allowlist_function_transition': attr.label(",
1395 " default = '//tools/allowlists/function_transition_allowlist',",
1396 " ),",
1397 " })");
1398 scratch.file(
1399 "test/BUILD",
1400 "load('//test:rules.bzl', 'my_rule')",
1401 "my_rule(name = 'bottom')",
1402 "genrule(name = 'test', srcs = [':bottom'], outs = ['out'], cmd = 'touch $@')");
1403 reporter.removeHandler(failFastHandler);
1404 assertThat(getConfiguredTarget("//test:test")).isNull();
1405 assertContainsEvent(
1406 "Output directory name '//bad:cpu' specified by CppConfiguration is invalid as part of a "
1407 + "path: must not contain /");
1408 }
juliexxiaa13f5902020-12-10 09:19:01 -08001409
1410 @Test
1411 public void testTransitionOnAllowMultiplesBuildSettingRequiresList() throws Exception {
juliexxiaa13f5902020-12-10 09:19:01 -08001412 scratch.file(
1413 "test/transitions.bzl",
1414 "def _transition_impl(settings, attr):",
1415 " return {'//test:cute-animal-fact': 'puffins mate for life'}",
1416 "my_transition = transition(",
1417 " implementation = _transition_impl,",
1418 " inputs = [],",
1419 " outputs = ['//test:cute-animal-fact']",
1420 ")");
1421 writeAllowlistFile();
1422 scratch.file(
1423 "test/rules.bzl",
1424 "load('//test:transitions.bzl', 'my_transition')",
1425 "def _rule_impl(ctx):",
1426 " return []",
1427 "my_rule = rule(",
1428 " implementation = _rule_impl,",
1429 " cfg = my_transition,",
1430 " attrs = {",
1431 " '_allowlist_function_transition': attr.label(",
1432 " default = '//tools/allowlists/function_transition_allowlist',",
1433 " ),",
1434 " },",
1435 ")");
1436 scratch.file(
1437 "test/build_settings.bzl",
1438 "def _impl(ctx):",
1439 " return []",
1440 "string_flag = rule(implementation = _impl, build_setting = config.string(flag=True,"
1441 + " allow_multiple=True))");
1442 scratch.file(
1443 "test/BUILD",
1444 "load('//test:rules.bzl', 'my_rule')",
1445 "load('//test:build_settings.bzl', 'string_flag')",
1446 "my_rule(name = 'test')",
1447 "string_flag(",
1448 " name = 'cute-animal-fact',",
1449 " build_setting_default = \"cats can't taste sugar\",",
1450 ")");
1451
1452 reporter.removeHandler(failFastHandler);
1453 getConfiguredTarget("//test");
1454 assertContainsEvent(
1455 "'//test:cute-animal-fact' allows multiple values and must be set in transition using a"
1456 + " starlark list instead of single value");
1457 }
1458
1459 @Test
1460 public void testTransitionOnAllowMultiplesBuildSetting() throws Exception {
juliexxiaa13f5902020-12-10 09:19:01 -08001461 scratch.file(
1462 "test/transitions.bzl",
1463 "def _transition_impl(settings, attr):",
1464 " return {'//test:cute-animal-fact': ['puffins mate for life']}",
1465 "my_transition = transition(",
1466 " implementation = _transition_impl,",
1467 " inputs = [],",
1468 " outputs = ['//test:cute-animal-fact']",
1469 ")");
1470 writeAllowlistFile();
1471 scratch.file(
1472 "test/rules.bzl",
1473 "load('//test:transitions.bzl', 'my_transition')",
1474 "def _rule_impl(ctx):",
1475 " return []",
1476 "my_rule = rule(",
1477 " implementation = _rule_impl,",
1478 " cfg = my_transition,",
1479 " attrs = {",
1480 " '_allowlist_function_transition': attr.label(",
1481 " default = '//tools/allowlists/function_transition_allowlist',",
1482 " ),",
1483 " },",
1484 ")");
1485 scratch.file(
1486 "test/build_settings.bzl",
1487 "def _impl(ctx):",
1488 " return []",
1489 "string_flag = rule(implementation = _impl, build_setting = config.string(flag=True,"
1490 + " allow_multiple=True))");
1491 scratch.file(
1492 "test/BUILD",
1493 "load('//test:rules.bzl', 'my_rule')",
1494 "load('//test:build_settings.bzl', 'string_flag')",
1495 "my_rule(name = 'test')",
1496 "string_flag(",
1497 " name = 'cute-animal-fact',",
1498 " build_setting_default = \"cats can't taste sugar\",",
1499 ")");
1500
1501 Map<Label, Object> starlarkOptions =
1502 getConfiguration(getConfiguredTarget("//test")).getOptions().getStarlarkOptions();
1503 assertNoEvents();
1504 assertThat(
1505 (List<?>) starlarkOptions.get(Label.parseAbsoluteUnchecked("//test:cute-animal-fact")))
1506 .containsExactly("puffins mate for life");
1507 }
gregced6795462020-12-14 11:06:45 -08001508
1509 /**
1510 * Changing --cpu implicitly changes the target platform. Test that the old value of --platforms
1511 * gets cleared out (platform mappings can then kick in to set --platforms correctly).
1512 */
1513 @Test
1514 public void testImplicitPlatformsChange() throws Exception {
1515 scratch.file("platforms/BUILD", "platform(name = 'my_platform', constraint_values = [])");
1516 scratch.file(
1517 "test/transitions.bzl",
1518 "def _transition_impl(settings, attr):",
1519 " return {'//command_line_option:cpu': 'ppc'}",
1520 "my_transition = transition(",
1521 " implementation = _transition_impl,",
1522 " inputs = [],",
1523 " outputs = ['//command_line_option:cpu']",
1524 ")");
1525 writeAllowlistFile();
1526 scratch.file(
1527 "test/rules.bzl",
1528 "load('//test:transitions.bzl', 'my_transition')",
1529 "def _rule_impl(ctx):",
1530 " return []",
1531 "my_rule = rule(",
1532 " implementation = _rule_impl,",
1533 " cfg = my_transition,",
1534 " attrs = {",
1535 " '_allowlist_function_transition': attr.label(",
1536 " default = '//tools/allowlists/function_transition_allowlist',",
1537 " ),",
1538 " },",
1539 ")");
1540 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
1541
1542 useConfiguration("--platforms=//platforms:my_platform");
1543 // When --platforms is empty and no platform mapping triggers, PlatformMappingValue sets
1544 // --platforms to PlatformOptions.computeTargetPlatform(), which defaults to the host.
1545 assertThat(
1546 getConfiguration(getConfiguredTarget("//test:test"))
1547 .getOptions()
1548 .get(PlatformOptions.class)
1549 .platforms)
1550 .containsExactly(
1551 Label.parseAbsoluteUnchecked(TestConstants.PLATFORM_PACKAGE_ROOT + ":default_host"));
1552 }
1553
1554 @Test
1555 public void testExplicitPlatformsChange() throws Exception {
1556 scratch.file(
1557 "platforms/BUILD",
1558 "platform(name = 'my_platform', constraint_values = [])",
1559 "platform(name = 'my_other_platform', constraint_values = [])");
1560 scratch.file(
1561 "test/transitions.bzl",
1562 "def _transition_impl(settings, attr):",
1563 " return {",
1564 " '//command_line_option:cpu': 'ppc',",
1565 " '//command_line_option:platforms': ['//platforms:my_other_platform']",
1566 " }",
1567 "my_transition = transition(",
1568 " implementation = _transition_impl,",
1569 " inputs = [],",
1570 " outputs = [",
1571 " '//command_line_option:cpu',",
1572 " '//command_line_option:platforms'",
1573 " ]",
1574 ")");
1575 writeAllowlistFile();
1576 scratch.file(
1577 "test/rules.bzl",
1578 "load('//test:transitions.bzl', 'my_transition')",
1579 "def _rule_impl(ctx):",
1580 " return []",
1581 "my_rule = rule(",
1582 " implementation = _rule_impl,",
1583 " cfg = my_transition,",
1584 " attrs = {",
1585 " '_allowlist_function_transition': attr.label(",
1586 " default = '//tools/allowlists/function_transition_allowlist',",
1587 " ),",
1588 " },",
1589 ")");
1590 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
1591
1592 useConfiguration("--platforms=//platforms:my_platform");
1593 assertThat(
1594 getConfiguration(getConfiguredTarget("//test:test"))
1595 .getOptions()
1596 .get(PlatformOptions.class)
1597 .platforms)
1598 .containsExactly(Label.parseAbsoluteUnchecked("//platforms:my_other_platform"));
1599 }
1600
1601 /* If the transition doesn't change --cpu, it doesn't constitute a platform change. */
1602 @Test
1603 public void testNoPlatformChange() throws Exception {
1604 scratch.file("platforms/BUILD", "platform(name = 'my_platform', constraint_values = [])");
1605 scratch.file(
1606 "test/transitions.bzl",
1607 "def _transition_impl(settings, attr):",
1608 " return {",
twigg4970e0f2021-03-31 15:34:49 -07001609 " '//command_line_option:foo': 'blah',",
gregced6795462020-12-14 11:06:45 -08001610 " }",
1611 "my_transition = transition(",
1612 " implementation = _transition_impl,",
1613 " inputs = [],",
1614 " outputs = [",
twigg4970e0f2021-03-31 15:34:49 -07001615 " '//command_line_option:foo',",
gregced6795462020-12-14 11:06:45 -08001616 " ]",
1617 ")");
1618 writeAllowlistFile();
1619 scratch.file(
1620 "test/rules.bzl",
1621 "load('//test:transitions.bzl', 'my_transition')",
1622 "def _rule_impl(ctx):",
1623 " return []",
1624 "my_rule = rule(",
1625 " implementation = _rule_impl,",
1626 " cfg = my_transition,",
1627 " attrs = {",
1628 " '_allowlist_function_transition': attr.label(",
1629 " default = '//tools/allowlists/function_transition_allowlist',",
1630 " ),",
1631 " },",
1632 ")");
1633 scratch.file("test/BUILD", "load('//test:rules.bzl', 'my_rule')", "my_rule(name = 'test')");
1634
1635 useConfiguration("--platforms=//platforms:my_platform");
1636 assertThat(
1637 getConfiguration(getConfiguredTarget("//test:test"))
1638 .getOptions()
1639 .get(PlatformOptions.class)
1640 .platforms)
1641 .containsExactly(Label.parseAbsoluteUnchecked("//platforms:my_platform"));
1642 }
juliexxiadeb028e2019-01-05 17:19:21 -08001643}