| // Copyright 2020 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.analysis; | 
 |  | 
 | import static com.google.common.truth.Truth.assertThat; | 
 |  | 
 | import com.google.devtools.build.lib.analysis.util.BuildViewTestCase; | 
 | import com.google.devtools.build.lib.cmdline.Label; | 
 | import com.google.devtools.build.lib.testutil.Scratch; | 
 | import java.util.Map; | 
 | import org.junit.Test; | 
 | import org.junit.runner.RunWith; | 
 | import org.junit.runners.JUnit4; | 
 |  | 
 | /** | 
 |  * Test of common logic between Starlark-defined transitions. Rule-transition- or | 
 |  * attr-transition-specific logic should be tested in {@link StarlarkRuleTransitionProviderTest} and | 
 |  * {@link StarlarkAttrTransitionProviderTest}. | 
 |  */ | 
 | @RunWith(JUnit4.class) | 
 | public class StarlarkTransitionTest extends BuildViewTestCase { | 
 |   static void writeAllowlistFile(Scratch scratch) throws Exception { | 
 |     scratch.overwriteFile( | 
 |         "tools/allowlists/function_transition_allowlist/BUILD", | 
 |         "package_group(", | 
 |         "    name = 'function_transition_allowlist',", | 
 |         "    packages = [", | 
 |         "        '//test/...',", | 
 |         "    ],", | 
 |         ")"); | 
 |   } | 
 |  | 
 |   @Test | 
 |   public void testDupeSettingsInInputsThrowsError() throws Exception { | 
 |     scratch.file( | 
 |         "test/defs.bzl", | 
 |         "def _setting_impl(ctx):", | 
 |         "  return []", | 
 |         "string_flag = rule(", | 
 |         "  implementation = _setting_impl,", | 
 |         "  build_setting = config.string(flag=True),", | 
 |         ")", | 
 |         "def _transition_impl(settings, attr):", | 
 |         "  return {'//test:formation': 'mesa'}", | 
 |         "formation_transition = transition(", | 
 |         "  implementation = _transition_impl,", | 
 |         "  inputs = ['@//test:formation', '//test:formation'],", // duplicates here | 
 |         "  outputs = ['//test:formation'],", | 
 |         ")", | 
 |         "def _impl(ctx):", | 
 |         "  return []", | 
 |         "state = rule(", | 
 |         "  implementation = _impl,", | 
 |         "  cfg = formation_transition,", | 
 |         "  attrs = {", | 
 |         "    '_allowlist_function_transition': attr.label(", | 
 |         "        default = '//tools/allowlists/function_transition_allowlist',", | 
 |         "    ),", | 
 |         "  })"); | 
 |     scratch.file( | 
 |         "test/BUILD", | 
 |         "load('//test:defs.bzl', 'state', 'string_flag')", | 
 |         "state(name = 'arizona')", | 
 |         "string_flag(name = 'formation', build_setting_default = 'canyon')"); | 
 |  | 
 |     reporter.removeHandler(failFastHandler); | 
 |     getConfiguredTarget("//test:arizona"); | 
 |     assertContainsEvent( | 
 |         "Transition declares duplicate build setting '@//test:formation' in INPUTS"); | 
 |   } | 
 |  | 
 |   @Test | 
 |   public void testDupeSettingsInOutputsThrowsError() throws Exception { | 
 |     scratch.file( | 
 |         "test/defs.bzl", | 
 |         "def _setting_impl(ctx):", | 
 |         "  return []", | 
 |         "string_flag = rule(", | 
 |         "  implementation = _setting_impl,", | 
 |         "  build_setting = config.string(flag=True),", | 
 |         ")", | 
 |         "def _transition_impl(settings, attr):", | 
 |         "  return {'//test:formation': 'mesa'}", | 
 |         "formation_transition = transition(", | 
 |         "  implementation = _transition_impl,", | 
 |         "  inputs = ['//test:formation'],", | 
 |         "  outputs = ['@//test:formation', '//test:formation'],", // duplicates here | 
 |         ")", | 
 |         "def _impl(ctx):", | 
 |         "  return []", | 
 |         "state = rule(", | 
 |         "  implementation = _impl,", | 
 |         "  cfg = formation_transition,", | 
 |         "  attrs = {", | 
 |         "    '_allowlist_function_transition': attr.label(", | 
 |         "        default = '//tools/allowlists/function_transition_allowlist',", | 
 |         "    ),", | 
 |         "  })"); | 
 |     scratch.file( | 
 |         "test/BUILD", | 
 |         "load('//test:defs.bzl', 'state', 'string_flag')", | 
 |         "state(name = 'arizona')", | 
 |         "string_flag(name = 'formation', build_setting_default = 'canyon')"); | 
 |  | 
 |     reporter.removeHandler(failFastHandler); | 
 |     getConfiguredTarget("//test:arizona"); | 
 |     assertContainsEvent( | 
 |         "Transition declares duplicate build setting '@//test:formation' in OUTPUTS"); | 
 |   } | 
 |  | 
 |   @Test | 
 |   public void testDifferentFormsOfFlagInInputsAndOutputs() throws Exception { | 
 |     writeAllowlistFile(scratch); | 
 |     scratch.file( | 
 |         "test/defs.bzl", | 
 |         "def _setting_impl(ctx):", | 
 |         "  return []", | 
 |         "string_flag = rule(", | 
 |         "  implementation = _setting_impl,", | 
 |         "  build_setting = config.string(flag=True),", | 
 |         ")", | 
 |         "def _transition_impl(settings, attr):", | 
 |         "  return {", | 
 |         "    '//test:formation': settings['@//test:formation']+'-transitioned',", | 
 |         "  }", | 
 |         "formation_transition = transition(", | 
 |         "  implementation = _transition_impl,", | 
 |         "  inputs = ['@//test:formation'],", | 
 |         "  outputs = ['//test:formation'],", | 
 |         ")", | 
 |         "def _impl(ctx):", | 
 |         "  return []", | 
 |         "state = rule(", | 
 |         "  implementation = _impl,", | 
 |         "  cfg = formation_transition,", | 
 |         "  attrs = {", | 
 |         "    '_allowlist_function_transition': attr.label(", | 
 |         "        default = '//tools/allowlists/function_transition_allowlist',", | 
 |         "    ),", | 
 |         "  })"); | 
 |     scratch.file( | 
 |         "test/BUILD", | 
 |         "load('//test:defs.bzl', 'state', 'string_flag')", | 
 |         "state(name = 'arizona')", | 
 |         "string_flag(name = 'formation', build_setting_default = 'canyon')"); | 
 |  | 
 |     Map<Label, Object> starlarkOptions = | 
 |         getConfiguration(getConfiguredTarget("//test:arizona")).getOptions().getStarlarkOptions(); | 
 |     assertThat(starlarkOptions).hasSize(1); | 
 |     assertThat(starlarkOptions.get(Label.parseAbsoluteUnchecked("//test:formation"))) | 
 |         .isEqualTo("canyon-transitioned"); | 
 |   } | 
 | } |