Michael Staib | b51251e | 2015-09-29 23:31:51 +0000 | [diff] [blame] | 1 | // Copyright 2015 The Bazel Authors. All rights reserved. |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 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 | package com.google.devtools.build.lib.packages; |
| 15 | |
| 16 | import static com.google.common.truth.Truth.assertThat; |
| 17 | import static com.google.common.truth.Truth.assertWithMessage; |
| 18 | import static com.google.devtools.build.lib.packages.Attribute.attr; |
Lukacs Berki | ffa73ad | 2015-09-18 11:40:12 +0000 | [diff] [blame] | 19 | import static com.google.devtools.build.lib.packages.BuildType.LABEL; |
| 20 | import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST; |
| 21 | import static com.google.devtools.build.lib.packages.BuildType.OUTPUT_LIST; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 22 | import static com.google.devtools.build.lib.packages.ImplicitOutputsFunction.substitutePlaceholderIntoTemplate; |
gregce | 74d84d4 | 2020-04-17 10:02:03 -0700 | [diff] [blame] | 23 | import static com.google.devtools.build.lib.packages.RuleClass.Builder.STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME; |
Lukacs Berki | 0e1a994 | 2015-06-18 08:53:18 +0000 | [diff] [blame] | 24 | import static com.google.devtools.build.lib.packages.RuleClass.NO_EXTERNAL_BINDINGS; |
John Cater | 39401a9 | 2020-07-09 10:12:55 -0700 | [diff] [blame^] | 25 | import static com.google.devtools.build.lib.packages.RuleClass.NO_TOOLCHAINS_TO_REGISTER; |
Googler | c5fcc86 | 2019-09-06 16:17:47 -0700 | [diff] [blame] | 26 | import static com.google.devtools.build.lib.packages.Type.BOOLEAN; |
| 27 | import static com.google.devtools.build.lib.packages.Type.INTEGER; |
| 28 | import static com.google.devtools.build.lib.packages.Type.STRING; |
| 29 | import static com.google.devtools.build.lib.packages.Type.STRING_LIST; |
michajlo | 660d17f | 2020-03-27 09:01:57 -0700 | [diff] [blame] | 30 | import static org.junit.Assert.assertThrows; |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 31 | import static org.junit.Assert.fail; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 32 | |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 33 | import com.google.common.base.Predicate; |
| 34 | import com.google.common.base.Predicates; |
michajlo | 0a89cef | 2020-04-06 12:04:12 -0700 | [diff] [blame] | 35 | import com.google.common.base.Strings; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 36 | import com.google.common.collect.ImmutableList; |
| 37 | import com.google.common.collect.ImmutableMap; |
| 38 | import com.google.common.collect.ImmutableSet; |
| 39 | import com.google.common.collect.Iterables; |
| 40 | import com.google.common.collect.Lists; |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 41 | import com.google.devtools.build.lib.actions.MutableActionGraph.ActionConflictException; |
jcater | a666f00 | 2020-04-14 14:55:20 -0700 | [diff] [blame] | 42 | import com.google.devtools.build.lib.analysis.config.Fragment; |
John Cater | b3b3e8b | 2019-04-03 09:18:42 -0700 | [diff] [blame] | 43 | import com.google.devtools.build.lib.analysis.config.transitions.TransitionFactory; |
Lukacs Berki | 6e91eb9 | 2015-09-21 09:12:37 +0000 | [diff] [blame] | 44 | import com.google.devtools.build.lib.cmdline.Label; |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 45 | import com.google.devtools.build.lib.cmdline.LabelSyntaxException; |
Kristina Chodorow | 73fa203 | 2015-08-28 17:57:46 +0000 | [diff] [blame] | 46 | import com.google.devtools.build.lib.cmdline.PackageIdentifier; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 47 | import com.google.devtools.build.lib.events.Event; |
| 48 | import com.google.devtools.build.lib.events.EventCollector; |
| 49 | import com.google.devtools.build.lib.events.EventKind; |
gregce | 18694cd | 2020-05-12 15:40:05 -0700 | [diff] [blame] | 50 | import com.google.devtools.build.lib.packages.Attribute.StarlarkComputedDefaultTemplate.CannotPrecomputeDefaultsException; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 51 | import com.google.devtools.build.lib.packages.Attribute.ValidityPredicate; |
Michael Staib | b51251e | 2015-09-29 23:31:51 +0000 | [diff] [blame] | 52 | import com.google.devtools.build.lib.packages.ConfigurationFragmentPolicy.MissingFragmentPolicy; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 53 | import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType; |
gregce | 4aa059a | 2019-02-26 13:20:47 -0800 | [diff] [blame] | 54 | import com.google.devtools.build.lib.packages.RuleClass.Builder.ThirdPartyLicenseExistencePolicy; |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 55 | import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory; |
Mark Schaller | ee62445 | 2016-01-13 18:41:24 +0000 | [diff] [blame] | 56 | import com.google.devtools.build.lib.packages.RuleFactory.BuildLangTypedAttributeValuesMap; |
Florian Weikert | cca703a | 2015-12-07 09:56:38 +0000 | [diff] [blame] | 57 | import com.google.devtools.build.lib.packages.util.PackageLoadingTestCase; |
adonovan | f5262c5 | 2020-04-02 09:25:14 -0700 | [diff] [blame] | 58 | import com.google.devtools.build.lib.syntax.Location; |
adonovan | f3a344e8 | 2019-12-11 11:10:11 -0800 | [diff] [blame] | 59 | import com.google.devtools.build.lib.syntax.StarlarkFunction; |
Klaus Aehlig | 2bb1bf9 | 2019-10-31 10:28:44 -0700 | [diff] [blame] | 60 | import com.google.devtools.build.lib.syntax.StarlarkSemantics; |
Googler | a3421e2 | 2019-09-26 06:48:32 -0700 | [diff] [blame] | 61 | import com.google.devtools.build.lib.syntax.StarlarkThread; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 62 | import com.google.devtools.build.lib.vfs.Path; |
janakr | 518bb87 | 2018-10-03 15:59:28 -0700 | [diff] [blame] | 63 | import com.google.devtools.build.lib.vfs.RootedPath; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 64 | import java.util.ArrayList; |
| 65 | import java.util.Arrays; |
| 66 | import java.util.Collections; |
| 67 | import java.util.HashMap; |
| 68 | import java.util.HashSet; |
| 69 | import java.util.Iterator; |
| 70 | import java.util.LinkedHashMap; |
| 71 | import java.util.List; |
| 72 | import java.util.Map; |
| 73 | import java.util.Set; |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 74 | import javax.annotation.Nullable; |
Florian Weikert | ea6c82d | 2016-09-05 12:15:31 +0000 | [diff] [blame] | 75 | import org.junit.Before; |
| 76 | import org.junit.Test; |
| 77 | import org.junit.runner.RunWith; |
| 78 | import org.junit.runners.JUnit4; |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 79 | |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 80 | /** |
| 81 | * Tests for {@link RuleClass}. |
| 82 | */ |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 83 | @RunWith(JUnit4.class) |
Florian Weikert | cca703a | 2015-12-07 09:56:38 +0000 | [diff] [blame] | 84 | public class RuleClassTest extends PackageLoadingTestCase { |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 85 | private static final RuleClass.ConfiguredTargetFactory<Object, Object, Exception> |
| 86 | DUMMY_CONFIGURED_TARGET_FACTORY = |
| 87 | new RuleClass.ConfiguredTargetFactory<Object, Object, Exception>() { |
| 88 | @Override |
| 89 | public Object create(Object ruleContext) |
| 90 | throws InterruptedException, RuleErrorException, ActionConflictException { |
| 91 | throw new IllegalStateException(); |
| 92 | } |
| 93 | }; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 94 | |
adonovan | ebb86fc | 2020-03-20 14:57:54 -0700 | [diff] [blame] | 95 | private static final ImmutableList<StarlarkThread.CallStackEntry> DUMMY_STACK = |
| 96 | ImmutableList.of( |
| 97 | new StarlarkThread.CallStackEntry( |
| 98 | "<toplevel>", Location.fromFileLineColumn("BUILD", 10, 1)), |
| 99 | new StarlarkThread.CallStackEntry("bar", Location.fromFileLineColumn("bar.bzl", 42, 1)), |
| 100 | new StarlarkThread.CallStackEntry("rule", Location.BUILTIN)); |
| 101 | |
jcater | a666f00 | 2020-04-14 14:55:20 -0700 | [diff] [blame] | 102 | private static final class DummyFragment extends Fragment {} |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 103 | |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 104 | private static final ImmutableList<StarlarkThread.CallStackEntry> NO_STACK = ImmutableList.of(); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 105 | |
| 106 | private static final Predicate<String> PREFERRED_DEPENDENCY_PREDICATE = Predicates.alwaysFalse(); |
| 107 | |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 108 | private static RuleClass createRuleClassA() throws LabelSyntaxException { |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 109 | return newRuleClass( |
| 110 | "ruleA", |
| 111 | false, |
| 112 | false, |
| 113 | false, |
| 114 | false, |
| 115 | false, |
| 116 | false, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 117 | false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 118 | ImplicitOutputsFunction.NONE, |
Cal Peyser | 19dda25 | 2017-01-11 23:37:05 +0000 | [diff] [blame] | 119 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 120 | DUMMY_CONFIGURED_TARGET_FACTORY, |
| 121 | PredicatesWithMessage.<Rule>alwaysTrue(), |
| 122 | PREFERRED_DEPENDENCY_PREDICATE, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 123 | AdvertisedProviderSet.EMPTY, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 124 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 125 | ImmutableSet.<Class<?>>of(), |
| 126 | MissingFragmentPolicy.FAIL_ANALYSIS, |
| 127 | true, |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 128 | attr("my-string-attr", STRING).mandatory().build(), |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 129 | attr("my-label-attr", LABEL) |
| 130 | .mandatory() |
| 131 | .legacyAllowAnyFileType() |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 132 | .value(Label.parseAbsolute("//default:label", ImmutableMap.of())) |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 133 | .build(), |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 134 | attr("my-labellist-attr", LABEL_LIST).mandatory().legacyAllowAnyFileType().build(), |
| 135 | attr("my-integer-attr", INTEGER).value(42).build(), |
| 136 | attr("my-string-attr2", STRING).mandatory().value((String) null).build(), |
| 137 | attr("my-stringlist-attr", STRING_LIST).build(), |
| 138 | attr("my-sorted-stringlist-attr", STRING_LIST).orderIndependent().build()); |
| 139 | } |
| 140 | |
| 141 | private static RuleClass createRuleClassB(RuleClass ruleClassA) { |
| 142 | // emulates attribute inheritance |
| 143 | List<Attribute> attributes = new ArrayList<>(ruleClassA.getAttributes()); |
| 144 | attributes.add(attr("another-string-attr", STRING).mandatory().build()); |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 145 | return newRuleClass( |
| 146 | "ruleB", |
| 147 | false, |
| 148 | false, |
| 149 | false, |
| 150 | false, |
| 151 | false, |
| 152 | false, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 153 | false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 154 | ImplicitOutputsFunction.NONE, |
Cal Peyser | 19dda25 | 2017-01-11 23:37:05 +0000 | [diff] [blame] | 155 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 156 | DUMMY_CONFIGURED_TARGET_FACTORY, |
| 157 | PredicatesWithMessage.<Rule>alwaysTrue(), |
| 158 | PREFERRED_DEPENDENCY_PREDICATE, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 159 | AdvertisedProviderSet.EMPTY, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 160 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 161 | ImmutableSet.<Class<?>>of(), |
| 162 | MissingFragmentPolicy.FAIL_ANALYSIS, |
| 163 | true, |
Lukacs Berki | 549bfce | 2016-04-22 15:29:12 +0000 | [diff] [blame] | 164 | attributes.toArray(new Attribute[0])); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 165 | } |
| 166 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 167 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 168 | public void testRuleClassBasics() throws Exception { |
| 169 | RuleClass ruleClassA = createRuleClassA(); |
| 170 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 171 | assertThat(ruleClassA.getName()).isEqualTo("ruleA"); |
| 172 | assertThat(ruleClassA.getAttributeCount()).isEqualTo(7); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 173 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 174 | assertThat((int) ruleClassA.getAttributeIndex("my-string-attr")).isEqualTo(0); |
| 175 | assertThat((int) ruleClassA.getAttributeIndex("my-label-attr")).isEqualTo(1); |
| 176 | assertThat((int) ruleClassA.getAttributeIndex("my-labellist-attr")).isEqualTo(2); |
| 177 | assertThat((int) ruleClassA.getAttributeIndex("my-integer-attr")).isEqualTo(3); |
| 178 | assertThat((int) ruleClassA.getAttributeIndex("my-string-attr2")).isEqualTo(4); |
| 179 | assertThat((int) ruleClassA.getAttributeIndex("my-stringlist-attr")).isEqualTo(5); |
| 180 | assertThat((int) ruleClassA.getAttributeIndex("my-sorted-stringlist-attr")).isEqualTo(6); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 181 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 182 | assertThat(ruleClassA.getAttributeByName("my-string-attr")) |
| 183 | .isEqualTo(ruleClassA.getAttribute(0)); |
| 184 | assertThat(ruleClassA.getAttributeByName("my-label-attr")) |
| 185 | .isEqualTo(ruleClassA.getAttribute(1)); |
| 186 | assertThat(ruleClassA.getAttributeByName("my-labellist-attr")) |
| 187 | .isEqualTo(ruleClassA.getAttribute(2)); |
| 188 | assertThat(ruleClassA.getAttributeByName("my-integer-attr")) |
| 189 | .isEqualTo(ruleClassA.getAttribute(3)); |
| 190 | assertThat(ruleClassA.getAttributeByName("my-string-attr2")) |
| 191 | .isEqualTo(ruleClassA.getAttribute(4)); |
| 192 | assertThat(ruleClassA.getAttributeByName("my-stringlist-attr")) |
| 193 | .isEqualTo(ruleClassA.getAttribute(5)); |
| 194 | assertThat(ruleClassA.getAttributeByName("my-sorted-stringlist-attr")) |
| 195 | .isEqualTo(ruleClassA.getAttribute(6)); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 196 | |
lberki | e355e77 | 2017-05-31 14:34:53 +0200 | [diff] [blame] | 197 | // default based on type |
| 198 | assertThat(ruleClassA.getAttribute(0).getDefaultValue(null)).isEqualTo(""); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 199 | assertThat(ruleClassA.getAttribute(1).getDefaultValue(null)) |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 200 | .isEqualTo(Label.parseAbsolute("//default:label", ImmutableMap.of())); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 201 | assertThat(ruleClassA.getAttribute(2).getDefaultValue(null)).isEqualTo(Collections.emptyList()); |
| 202 | assertThat(ruleClassA.getAttribute(3).getDefaultValue(null)).isEqualTo(42); |
lberki | e355e77 | 2017-05-31 14:34:53 +0200 | [diff] [blame] | 203 | // default explicitly specified |
| 204 | assertThat(ruleClassA.getAttribute(4).getDefaultValue(null)).isNull(); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 205 | assertThat(ruleClassA.getAttribute(5).getDefaultValue(null)).isEqualTo(Collections.emptyList()); |
| 206 | assertThat(ruleClassA.getAttribute(6).getDefaultValue(null)).isEqualTo(Collections.emptyList()); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 207 | } |
| 208 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 209 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 210 | public void testRuleClassInheritance() throws Exception { |
| 211 | RuleClass ruleClassA = createRuleClassA(); |
| 212 | RuleClass ruleClassB = createRuleClassB(ruleClassA); |
| 213 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 214 | assertThat(ruleClassB.getName()).isEqualTo("ruleB"); |
| 215 | assertThat(ruleClassB.getAttributeCount()).isEqualTo(8); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 216 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 217 | assertThat((int) ruleClassB.getAttributeIndex("my-string-attr")).isEqualTo(0); |
| 218 | assertThat((int) ruleClassB.getAttributeIndex("my-label-attr")).isEqualTo(1); |
| 219 | assertThat((int) ruleClassB.getAttributeIndex("my-labellist-attr")).isEqualTo(2); |
| 220 | assertThat((int) ruleClassB.getAttributeIndex("my-integer-attr")).isEqualTo(3); |
| 221 | assertThat((int) ruleClassB.getAttributeIndex("my-string-attr2")).isEqualTo(4); |
| 222 | assertThat((int) ruleClassB.getAttributeIndex("my-stringlist-attr")).isEqualTo(5); |
| 223 | assertThat((int) ruleClassB.getAttributeIndex("my-sorted-stringlist-attr")).isEqualTo(6); |
| 224 | assertThat((int) ruleClassB.getAttributeIndex("another-string-attr")).isEqualTo(7); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 225 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 226 | assertThat(ruleClassB.getAttributeByName("my-string-attr")) |
| 227 | .isEqualTo(ruleClassB.getAttribute(0)); |
| 228 | assertThat(ruleClassB.getAttributeByName("my-label-attr")) |
| 229 | .isEqualTo(ruleClassB.getAttribute(1)); |
| 230 | assertThat(ruleClassB.getAttributeByName("my-labellist-attr")) |
| 231 | .isEqualTo(ruleClassB.getAttribute(2)); |
| 232 | assertThat(ruleClassB.getAttributeByName("my-integer-attr")) |
| 233 | .isEqualTo(ruleClassB.getAttribute(3)); |
| 234 | assertThat(ruleClassB.getAttributeByName("my-string-attr2")) |
| 235 | .isEqualTo(ruleClassB.getAttribute(4)); |
| 236 | assertThat(ruleClassB.getAttributeByName("my-stringlist-attr")) |
| 237 | .isEqualTo(ruleClassB.getAttribute(5)); |
| 238 | assertThat(ruleClassB.getAttributeByName("my-sorted-stringlist-attr")) |
| 239 | .isEqualTo(ruleClassB.getAttribute(6)); |
| 240 | assertThat(ruleClassB.getAttributeByName("another-string-attr")) |
| 241 | .isEqualTo(ruleClassB.getAttribute(7)); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 242 | } |
| 243 | |
| 244 | private static final String TEST_PACKAGE_NAME = "testpackage"; |
| 245 | |
| 246 | private static final String TEST_RULE_NAME = "my-rule-A"; |
| 247 | |
| 248 | private static final int TEST_RULE_DEFINED_AT_LINE = 42; |
| 249 | |
Brian Silverman | d7d6d62 | 2016-03-17 09:53:39 +0000 | [diff] [blame] | 250 | private static final String TEST_RULE_LABEL = "@//" + TEST_PACKAGE_NAME + ":" + TEST_RULE_NAME; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 251 | |
| 252 | private Path testBuildfilePath; |
| 253 | private Location testRuleLocation; |
| 254 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 255 | @Before |
| 256 | public final void setRuleLocation() throws Exception { |
janakr | 518bb87 | 2018-10-03 15:59:28 -0700 | [diff] [blame] | 257 | testBuildfilePath = root.getRelative("testpackage/BUILD"); |
adonovan | 22096af | 2020-01-08 07:09:52 -0800 | [diff] [blame] | 258 | testRuleLocation = |
| 259 | Location.fromFileLineColumn(testBuildfilePath.toString(), TEST_RULE_DEFINED_AT_LINE, 0); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 260 | } |
| 261 | |
| 262 | private Package.Builder createDummyPackageBuilder() { |
janakr | 518bb87 | 2018-10-03 15:59:28 -0700 | [diff] [blame] | 263 | return packageFactory |
Klaus Aehlig | 2bb1bf9 | 2019-10-31 10:28:44 -0700 | [diff] [blame] | 264 | .newPackageBuilder( |
| 265 | PackageIdentifier.createInMainRepo(TEST_PACKAGE_NAME), |
| 266 | "TESTING", |
adonovan | b85d0b7 | 2020-05-08 11:59:19 -0700 | [diff] [blame] | 267 | StarlarkSemantics.DEFAULT) |
janakr | 518bb87 | 2018-10-03 15:59:28 -0700 | [diff] [blame] | 268 | .setFilename(RootedPath.toRootedPath(root, testBuildfilePath)); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 269 | } |
| 270 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 271 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 272 | public void testDuplicatedDeps() throws Exception { |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 273 | RuleClass depsRuleClass = |
| 274 | newRuleClass( |
| 275 | "ruleDeps", |
| 276 | false, |
| 277 | false, |
| 278 | false, |
| 279 | false, |
| 280 | false, |
| 281 | false, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 282 | false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 283 | ImplicitOutputsFunction.NONE, |
Cal Peyser | 19dda25 | 2017-01-11 23:37:05 +0000 | [diff] [blame] | 284 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 285 | DUMMY_CONFIGURED_TARGET_FACTORY, |
| 286 | PredicatesWithMessage.<Rule>alwaysTrue(), |
| 287 | PREFERRED_DEPENDENCY_PREDICATE, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 288 | AdvertisedProviderSet.EMPTY, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 289 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 290 | ImmutableSet.<Class<?>>of(), |
| 291 | MissingFragmentPolicy.FAIL_ANALYSIS, |
| 292 | true, |
| 293 | attr("list1", LABEL_LIST).mandatory().legacyAllowAnyFileType().build(), |
| 294 | attr("list2", LABEL_LIST).mandatory().legacyAllowAnyFileType().build(), |
| 295 | attr("list3", LABEL_LIST).mandatory().legacyAllowAnyFileType().build()); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 296 | |
| 297 | // LinkedHashMap -> predictable iteration order for testing |
| 298 | Map<String, Object> attributeValues = new LinkedHashMap<>(); |
| 299 | attributeValues.put("list1", Lists.newArrayList("//testpackage:dup1", ":dup1", ":nodup")); |
| 300 | attributeValues.put("list2", Lists.newArrayList(":nodup1", ":nodup2")); |
| 301 | attributeValues.put("list3", Lists.newArrayList(":dup1", ":dup1", ":dup2", ":dup2")); |
| 302 | |
| 303 | reporter.removeHandler(failFastHandler); |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 304 | createRule(depsRuleClass, "depsRule", attributeValues, testRuleLocation, NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 305 | |
cpovirk | a4d3da6 | 2019-05-02 14:27:33 -0700 | [diff] [blame] | 306 | assertThat(eventCollector.count()).isSameInstanceAs(3); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 307 | assertDupError("//testpackage:dup1", "list1", "depsRule"); |
| 308 | assertDupError("//testpackage:dup1", "list3", "depsRule"); |
| 309 | assertDupError("//testpackage:dup2", "list3", "depsRule"); |
| 310 | } |
| 311 | |
| 312 | private void assertDupError(String label, String attrName, String ruleName) { |
| 313 | assertContainsEvent(String.format("Label '%s' is duplicated in the '%s' attribute of rule '%s'", |
| 314 | label, attrName, ruleName)); |
| 315 | } |
| 316 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 317 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 318 | public void testCreateRuleWithLegacyPublicVisibility() throws Exception { |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 319 | RuleClass ruleClass = |
| 320 | newRuleClass( |
| 321 | "ruleVis", |
| 322 | false, |
| 323 | false, |
| 324 | false, |
| 325 | false, |
| 326 | false, |
| 327 | false, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 328 | false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 329 | ImplicitOutputsFunction.NONE, |
Cal Peyser | 19dda25 | 2017-01-11 23:37:05 +0000 | [diff] [blame] | 330 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 331 | DUMMY_CONFIGURED_TARGET_FACTORY, |
| 332 | PredicatesWithMessage.<Rule>alwaysTrue(), |
| 333 | PREFERRED_DEPENDENCY_PREDICATE, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 334 | AdvertisedProviderSet.EMPTY, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 335 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 336 | ImmutableSet.<Class<?>>of(), |
| 337 | MissingFragmentPolicy.FAIL_ANALYSIS, |
| 338 | true, |
| 339 | attr("visibility", LABEL_LIST).legacyAllowAnyFileType().build()); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 340 | Map<String, Object> attributeValues = new HashMap<>(); |
| 341 | attributeValues.put("visibility", Arrays.asList("//visibility:legacy_public")); |
| 342 | |
| 343 | reporter.removeHandler(failFastHandler); |
| 344 | EventCollector collector = new EventCollector(EventKind.ERRORS); |
| 345 | reporter.addHandler(collector); |
| 346 | |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 347 | createRule(ruleClass, TEST_RULE_NAME, attributeValues, testRuleLocation, NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 348 | |
| 349 | assertContainsEvent("//visibility:legacy_public only allowed in package declaration"); |
| 350 | } |
| 351 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 352 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 353 | public void testCreateRule() throws Exception { |
| 354 | RuleClass ruleClassA = createRuleClassA(); |
| 355 | |
| 356 | // LinkedHashMap -> predictable iteration order for testing |
| 357 | Map<String, Object> attributeValues = new LinkedHashMap<>(); |
| 358 | attributeValues.put("my-labellist-attr", "foobar"); // wrong type |
| 359 | attributeValues.put("bogus-attr", "foobar"); // no such attr |
| 360 | attributeValues.put("my-stringlist-attr", Arrays.asList("foo", "bar")); |
| 361 | |
| 362 | reporter.removeHandler(failFastHandler); |
| 363 | EventCollector collector = new EventCollector(EventKind.ERRORS); |
| 364 | reporter.addHandler(collector); |
| 365 | |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 366 | Rule rule = createRule(ruleClassA, TEST_RULE_NAME, attributeValues, testRuleLocation, NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 367 | |
| 368 | // TODO(blaze-team): (2009) refactor to use assertContainsEvent |
| 369 | Iterator<String> expectedMessages = Arrays.asList( |
| 370 | "expected value of type 'list(label)' for attribute 'my-labellist-attr' " |
Francois-Rene Rideau | d61f531 | 2015-06-13 03:34:47 +0000 | [diff] [blame] | 371 | + "in 'ruleA' rule, but got \"foobar\" (string)", |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 372 | "no such attribute 'bogus-attr' in 'ruleA' rule", |
| 373 | "missing value for mandatory " |
| 374 | + "attribute 'my-string-attr' in 'ruleA' rule", |
| 375 | "missing value for mandatory attribute 'my-label-attr' in 'ruleA' rule", |
| 376 | "missing value for mandatory " |
| 377 | + "attribute 'my-labellist-attr' in 'ruleA' rule", |
| 378 | "missing value for mandatory " |
| 379 | + "attribute 'my-string-attr2' in 'ruleA' rule" |
| 380 | ).iterator(); |
| 381 | |
| 382 | for (Event event : collector) { |
adonovan | 22096af | 2020-01-08 07:09:52 -0800 | [diff] [blame] | 383 | assertThat(event.getLocation().line()).isEqualTo(TEST_RULE_DEFINED_AT_LINE); |
| 384 | assertThat(event.getLocation().file()).isEqualTo(testBuildfilePath.toString()); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 385 | assertThat(event.getMessage()) |
| 386 | .isEqualTo(TEST_RULE_LABEL.toString().substring(1) + ": " + expectedMessages.next()); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 387 | } |
| 388 | |
| 389 | // Test basic rule properties: |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 390 | assertThat(rule.getRuleClass()).isEqualTo("ruleA"); |
| 391 | assertThat(rule.getName()).isEqualTo(TEST_RULE_NAME); |
| 392 | assertThat(rule.getLabel().toString()).isEqualTo(TEST_RULE_LABEL.substring(1)); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 393 | |
| 394 | // Test attribute access: |
| 395 | AttributeMap attributes = RawAttributeMapper.of(rule); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 396 | assertThat(attributes.get("my-label-attr", BuildType.LABEL).toString()) |
| 397 | .isEqualTo("//default:label"); |
| 398 | assertThat(attributes.get("my-integer-attr", Type.INTEGER).intValue()).isEqualTo(42); |
lberki | e355e77 | 2017-05-31 14:34:53 +0200 | [diff] [blame] | 399 | // missing attribute -> default chosen based on type |
| 400 | assertThat(attributes.get("my-string-attr", Type.STRING)).isEmpty(); |
Lukacs Berki | ffa73ad | 2015-09-18 11:40:12 +0000 | [diff] [blame] | 401 | assertThat(attributes.get("my-labellist-attr", BuildType.LABEL_LIST)).isEmpty(); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 402 | assertThat(attributes.get("my-stringlist-attr", Type.STRING_LIST)) |
| 403 | .isEqualTo(Arrays.asList("foo", "bar")); |
jcater | b922677 | 2019-04-29 12:04:52 -0700 | [diff] [blame] | 404 | IllegalArgumentException e = |
| 405 | assertThrows( |
| 406 | IllegalArgumentException.class, () -> attributes.get("my-labellist-attr", Type.STRING)); |
| 407 | assertThat(e) |
| 408 | .hasMessageThat() |
| 409 | .isEqualTo( |
| 410 | "Attribute my-labellist-attr is of type list(label) " |
| 411 | + "and not of type string in ruleA rule //testpackage:my-rule-A"); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 412 | } |
| 413 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 414 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 415 | public void testImplicitOutputs() throws Exception { |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 416 | RuleClass ruleClassC = |
| 417 | newRuleClass( |
| 418 | "ruleC", |
| 419 | false, |
| 420 | false, |
| 421 | false, |
| 422 | false, |
| 423 | false, |
| 424 | false, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 425 | false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 426 | ImplicitOutputsFunction.fromTemplates( |
| 427 | "foo-%{name}.bar", "lib%{name}-wazoo-%{name}.mumble", "stuff-%{outs}-bar"), |
Cal Peyser | 19dda25 | 2017-01-11 23:37:05 +0000 | [diff] [blame] | 428 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 429 | DUMMY_CONFIGURED_TARGET_FACTORY, |
| 430 | PredicatesWithMessage.<Rule>alwaysTrue(), |
| 431 | PREFERRED_DEPENDENCY_PREDICATE, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 432 | AdvertisedProviderSet.EMPTY, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 433 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 434 | ImmutableSet.<Class<?>>of(), |
| 435 | MissingFragmentPolicy.FAIL_ANALYSIS, |
| 436 | true, |
Benjamin Peterson | 11b8760 | 2017-04-12 19:53:07 +0000 | [diff] [blame] | 437 | attr("name", STRING).build(), |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 438 | attr("outs", OUTPUT_LIST).build()); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 439 | |
| 440 | Map<String, Object> attributeValues = new HashMap<>(); |
| 441 | attributeValues.put("outs", Collections.singletonList("explicit_out")); |
Benjamin Peterson | 11b8760 | 2017-04-12 19:53:07 +0000 | [diff] [blame] | 442 | attributeValues.put("name", "myrule"); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 443 | |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 444 | Rule rule = createRule(ruleClassC, "myrule", attributeValues, testRuleLocation, NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 445 | |
| 446 | Set<String> set = new HashSet<>(); |
| 447 | for (OutputFile outputFile : rule.getOutputFiles()) { |
| 448 | set.add(outputFile.getName()); |
cpovirk | a4d3da6 | 2019-05-02 14:27:33 -0700 | [diff] [blame] | 449 | assertThat(outputFile.getGeneratingRule()).isSameInstanceAs(rule); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 450 | } |
| 451 | assertThat(set).containsExactly("foo-myrule.bar", "libmyrule-wazoo-myrule.mumble", |
| 452 | "stuff-explicit_out-bar", "explicit_out"); |
| 453 | } |
| 454 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 455 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 456 | public void testImplicitOutsWithBasenameDirname() throws Exception { |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 457 | RuleClass ruleClass = |
| 458 | newRuleClass( |
| 459 | "ruleClass", |
| 460 | false, |
| 461 | false, |
| 462 | false, |
| 463 | false, |
| 464 | false, |
| 465 | false, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 466 | false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 467 | ImplicitOutputsFunction.fromTemplates("%{dirname}lib%{basename}.bar"), |
Cal Peyser | 19dda25 | 2017-01-11 23:37:05 +0000 | [diff] [blame] | 468 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 469 | DUMMY_CONFIGURED_TARGET_FACTORY, |
| 470 | PredicatesWithMessage.<Rule>alwaysTrue(), |
| 471 | PREFERRED_DEPENDENCY_PREDICATE, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 472 | AdvertisedProviderSet.EMPTY, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 473 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 474 | ImmutableSet.<Class<?>>of(), |
| 475 | MissingFragmentPolicy.FAIL_ANALYSIS, |
| 476 | true); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 477 | |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 478 | Rule rule = createRule(ruleClass, "myRule", ImmutableMap.of(), testRuleLocation, NO_STACK); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 479 | assertThat(Iterables.getOnlyElement(rule.getOutputFiles()).getName()) |
| 480 | .isEqualTo("libmyRule.bar"); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 481 | |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 482 | Rule ruleWithSlash = |
| 483 | createRule(ruleClass, "myRule/with/slash", ImmutableMap.of(), testRuleLocation, NO_STACK); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 484 | assertThat(Iterables.getOnlyElement(ruleWithSlash.getOutputFiles()).getName()) |
| 485 | .isEqualTo("myRule/with/libslash.bar"); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 486 | } |
| 487 | |
| 488 | /** |
| 489 | * Helper routine that instantiates a rule class with the given computed default and supporting |
| 490 | * attributes for the default to reference. |
| 491 | */ |
| 492 | private static RuleClass getRuleClassWithComputedDefault(Attribute computedDefault) { |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 493 | return newRuleClass( |
| 494 | "ruleClass", |
| 495 | false, |
| 496 | false, |
| 497 | false, |
| 498 | false, |
| 499 | false, |
| 500 | false, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 501 | false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 502 | ImplicitOutputsFunction.fromTemplates("empty"), |
Cal Peyser | 19dda25 | 2017-01-11 23:37:05 +0000 | [diff] [blame] | 503 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 504 | DUMMY_CONFIGURED_TARGET_FACTORY, |
| 505 | PredicatesWithMessage.<Rule>alwaysTrue(), |
| 506 | PREFERRED_DEPENDENCY_PREDICATE, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 507 | AdvertisedProviderSet.EMPTY, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 508 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 509 | ImmutableSet.<Class<?>>of(), |
| 510 | MissingFragmentPolicy.FAIL_ANALYSIS, |
| 511 | true, |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 512 | attr("condition", BOOLEAN).value(false).build(), |
| 513 | attr("declared1", BOOLEAN).value(false).build(), |
| 514 | attr("declared2", BOOLEAN).value(false).build(), |
| 515 | attr("nonconfigurable", BOOLEAN).nonconfigurable("test").value(false).build(), |
| 516 | computedDefault); |
| 517 | } |
| 518 | |
| 519 | /** |
| 520 | * Helper routine that checks that a computed default is valid and bound to the expected value. |
| 521 | */ |
| 522 | private void checkValidComputedDefault(Object expectedValue, Attribute computedDefault, |
| 523 | ImmutableMap<String, Object> attrValueMap) throws Exception { |
juliexxia | 84d1a66 | 2018-12-26 14:07:04 -0800 | [diff] [blame] | 524 | assertThat(computedDefault.getDefaultValueUnchecked()) |
| 525 | .isInstanceOf(Attribute.ComputedDefault.class); |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 526 | Rule rule = |
| 527 | createRule( |
| 528 | getRuleClassWithComputedDefault(computedDefault), |
| 529 | "myRule", |
| 530 | attrValueMap, |
| 531 | testRuleLocation, |
| 532 | NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 533 | AttributeMap attributes = RawAttributeMapper.of(rule); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 534 | assertThat(attributes.get(computedDefault.getName(), computedDefault.getType())) |
| 535 | .isEqualTo(expectedValue); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 536 | } |
| 537 | |
| 538 | /** |
| 539 | * Helper routine that checks that a computed default is invalid due to declared dependency |
| 540 | * issues and fails with the expected message. |
| 541 | */ |
| 542 | private void checkInvalidComputedDefault(Attribute computedDefault, String expectedMessage) |
| 543 | throws Exception { |
jcater | b922677 | 2019-04-29 12:04:52 -0700 | [diff] [blame] | 544 | IllegalArgumentException e = |
| 545 | assertThrows( |
| 546 | IllegalArgumentException.class, |
| 547 | () -> |
| 548 | createRule( |
| 549 | getRuleClassWithComputedDefault(computedDefault), |
| 550 | "myRule", |
| 551 | ImmutableMap.<String, Object>of(), |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 552 | testRuleLocation, |
| 553 | NO_STACK)); |
jcater | b922677 | 2019-04-29 12:04:52 -0700 | [diff] [blame] | 554 | assertThat(e).hasMessageThat().isEqualTo(expectedMessage); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 555 | } |
| 556 | |
| 557 | /** |
| 558 | * Tests computed default values are computed as expected. |
| 559 | */ |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 560 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 561 | public void testComputedDefault() throws Exception { |
| 562 | Attribute computedDefault = |
| 563 | attr("$result", BOOLEAN).value(new Attribute.ComputedDefault("condition") { |
| 564 | @Override |
| 565 | public Object getDefault(AttributeMap rule) { |
| 566 | return rule.get("condition", Type.BOOLEAN); |
| 567 | } |
| 568 | }).build(); |
| 569 | |
| 570 | checkValidComputedDefault(Boolean.FALSE, computedDefault, |
| 571 | ImmutableMap.<String, Object>of("condition", Boolean.FALSE)); |
| 572 | checkValidComputedDefault(Boolean.TRUE, computedDefault, |
| 573 | ImmutableMap.<String, Object>of("condition", Boolean.TRUE)); |
| 574 | } |
| 575 | |
| 576 | /** |
| 577 | * Tests that computed defaults can only read attribute values for configurable attributes that |
| 578 | * have been explicitly declared. |
| 579 | */ |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 580 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 581 | public void testComputedDefaultDeclarations() throws Exception { |
| 582 | checkValidComputedDefault( |
| 583 | Boolean.FALSE, |
| 584 | attr("$good_default_no_declares", BOOLEAN).value( |
| 585 | new Attribute.ComputedDefault() { |
| 586 | @Override public Object getDefault(AttributeMap rule) { |
| 587 | // OK: not a value check: |
| 588 | return rule.isAttributeValueExplicitlySpecified("undeclared"); |
| 589 | } |
| 590 | }).build(), |
| 591 | ImmutableMap.<String, Object>of()); |
| 592 | |
| 593 | checkValidComputedDefault( |
| 594 | Boolean.FALSE, |
| 595 | attr("$good_default_one_declare", BOOLEAN).value( |
| 596 | new Attribute.ComputedDefault("declared1") { |
| 597 | @Override public Object getDefault(AttributeMap rule) { |
| 598 | return rule.get("declared1", Type.BOOLEAN); |
| 599 | } |
| 600 | }).build(), |
| 601 | ImmutableMap.<String, Object>of()); |
| 602 | |
| 603 | checkValidComputedDefault( |
| 604 | Boolean.FALSE, |
| 605 | attr("$good_default_two_declares", BOOLEAN).value( |
| 606 | new Attribute.ComputedDefault("declared1", "declared2") { |
| 607 | @Override public Object getDefault(AttributeMap rule) { |
| 608 | return rule.get("declared1", Type.BOOLEAN) && rule.get("declared2", Type.BOOLEAN); |
| 609 | } |
| 610 | }).build(), |
| 611 | ImmutableMap.<String, Object>of()); |
| 612 | |
| 613 | checkInvalidComputedDefault( |
| 614 | attr("$bad_default_no_declares", BOOLEAN).value( |
| 615 | new Attribute.ComputedDefault() { |
| 616 | @Override public Object getDefault(AttributeMap rule) { |
| 617 | return rule.get("declared1", Type.BOOLEAN); |
| 618 | } |
| 619 | }).build(), |
| 620 | "attribute \"declared1\" isn't available in this computed default context"); |
| 621 | |
| 622 | checkInvalidComputedDefault( |
| 623 | attr("$bad_default_one_declare", BOOLEAN).value( |
| 624 | new Attribute.ComputedDefault("declared1") { |
| 625 | @Override public Object getDefault(AttributeMap rule) { |
| 626 | return rule.get("declared1", Type.BOOLEAN) || rule.get("declared2", Type.BOOLEAN); |
| 627 | } |
| 628 | }).build(), |
| 629 | "attribute \"declared2\" isn't available in this computed default context"); |
| 630 | |
| 631 | checkInvalidComputedDefault( |
| 632 | attr("$bad_default_two_declares", BOOLEAN).value( |
| 633 | new Attribute.ComputedDefault("declared1", "declared2") { |
| 634 | @Override public Object getDefault(AttributeMap rule) { |
| 635 | return rule.get("condition", Type.BOOLEAN); |
| 636 | } |
| 637 | }).build(), |
| 638 | "attribute \"condition\" isn't available in this computed default context"); |
| 639 | } |
| 640 | |
| 641 | /** |
| 642 | * Tests that computed defaults *can* read attribute values for non-configurable attributes |
| 643 | * without needing to explicitly declare them. |
| 644 | */ |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 645 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 646 | public void testComputedDefaultWithNonConfigurableAttributes() throws Exception { |
| 647 | checkValidComputedDefault( |
| 648 | Boolean.FALSE, |
| 649 | attr("$good_default_reading_undeclared_nonconfigurable_attribute", BOOLEAN).value( |
| 650 | new Attribute.ComputedDefault() { |
| 651 | @Override public Object getDefault(AttributeMap rule) { |
| 652 | return rule.get("nonconfigurable", Type.BOOLEAN); |
| 653 | } |
| 654 | }).build(), |
| 655 | ImmutableMap.<String, Object>of()); |
| 656 | } |
| 657 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 658 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 659 | public void testOutputsAreOrdered() throws Exception { |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 660 | RuleClass ruleClassC = |
| 661 | newRuleClass( |
| 662 | "ruleC", |
| 663 | false, |
| 664 | false, |
| 665 | false, |
| 666 | false, |
| 667 | false, |
| 668 | false, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 669 | false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 670 | ImplicitOutputsFunction.fromTemplates("first-%{name}", "second-%{name}", "out-%{outs}"), |
Cal Peyser | 19dda25 | 2017-01-11 23:37:05 +0000 | [diff] [blame] | 671 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 672 | DUMMY_CONFIGURED_TARGET_FACTORY, |
| 673 | PredicatesWithMessage.<Rule>alwaysTrue(), |
| 674 | PREFERRED_DEPENDENCY_PREDICATE, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 675 | AdvertisedProviderSet.EMPTY, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 676 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 677 | ImmutableSet.<Class<?>>of(), |
| 678 | MissingFragmentPolicy.FAIL_ANALYSIS, |
| 679 | true, |
Benjamin Peterson | 11b8760 | 2017-04-12 19:53:07 +0000 | [diff] [blame] | 680 | attr("name", STRING).build(), |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 681 | attr("outs", OUTPUT_LIST).build()); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 682 | |
| 683 | Map<String, Object> attributeValues = new HashMap<>(); |
| 684 | attributeValues.put("outs", ImmutableList.of("third", "fourth")); |
Benjamin Peterson | 11b8760 | 2017-04-12 19:53:07 +0000 | [diff] [blame] | 685 | attributeValues.put("name", "myrule"); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 686 | |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 687 | Rule rule = createRule(ruleClassC, "myrule", attributeValues, testRuleLocation, NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 688 | |
| 689 | List<String> actual = new ArrayList<>(); |
| 690 | for (OutputFile outputFile : rule.getOutputFiles()) { |
| 691 | actual.add(outputFile.getName()); |
cpovirk | a4d3da6 | 2019-05-02 14:27:33 -0700 | [diff] [blame] | 692 | assertThat(outputFile.getGeneratingRule()).isSameInstanceAs(rule); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 693 | } |
| 694 | assertWithMessage("unexpected output set").that(actual).containsExactly("first-myrule", |
| 695 | "second-myrule", "out-third", "out-fourth", "third", "fourth"); |
| 696 | assertWithMessage("invalid output ordering").that(actual).containsExactly("first-myrule", |
| 697 | "second-myrule", "out-third", "out-fourth", "third", "fourth").inOrder(); |
| 698 | } |
| 699 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 700 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 701 | public void testSubstitutePlaceholderIntoTemplate() throws Exception { |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 702 | RuleClass ruleClass = |
| 703 | newRuleClass( |
| 704 | "ruleA", |
| 705 | false, |
| 706 | false, |
| 707 | false, |
| 708 | false, |
| 709 | false, |
| 710 | false, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 711 | false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 712 | ImplicitOutputsFunction.NONE, |
Cal Peyser | 19dda25 | 2017-01-11 23:37:05 +0000 | [diff] [blame] | 713 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 714 | DUMMY_CONFIGURED_TARGET_FACTORY, |
| 715 | PredicatesWithMessage.<Rule>alwaysTrue(), |
| 716 | PREFERRED_DEPENDENCY_PREDICATE, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 717 | AdvertisedProviderSet.EMPTY, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 718 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 719 | ImmutableSet.<Class<?>>of(), |
| 720 | MissingFragmentPolicy.FAIL_ANALYSIS, |
| 721 | true, |
| 722 | attr("a", STRING_LIST).mandatory().build(), |
| 723 | attr("b", STRING_LIST).mandatory().build(), |
| 724 | attr("c", STRING_LIST).mandatory().build(), |
| 725 | attr("baz", STRING_LIST).mandatory().build(), |
| 726 | attr("empty", STRING_LIST).build()); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 727 | |
| 728 | Map<String, Object> attributeValues = new LinkedHashMap<>(); |
| 729 | attributeValues.put("a", ImmutableList.of("a", "A")); |
| 730 | attributeValues.put("b", ImmutableList.of("b", "B")); |
| 731 | attributeValues.put("c", ImmutableList.of("c", "C")); |
| 732 | attributeValues.put("baz", ImmutableList.of("baz", "BAZ")); |
| 733 | attributeValues.put("empty", ImmutableList.<String>of()); |
| 734 | |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 735 | AttributeMap rule = |
| 736 | RawAttributeMapper.of( |
| 737 | createRule(ruleClass, "testrule", attributeValues, testRuleLocation, NO_STACK)); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 738 | |
| 739 | assertThat(substitutePlaceholderIntoTemplate("foo", rule)).containsExactly("foo"); |
| 740 | assertThat(substitutePlaceholderIntoTemplate("foo-%{baz}-bar", rule)).containsExactly( |
| 741 | "foo-baz-bar", "foo-BAZ-bar").inOrder(); |
| 742 | assertThat(substitutePlaceholderIntoTemplate("%{a}-%{b}-%{c}", rule)).containsExactly("a-b-c", |
| 743 | "a-b-C", "a-B-c", "a-B-C", "A-b-c", "A-b-C", "A-B-c", "A-B-C").inOrder(); |
| 744 | assertThat(substitutePlaceholderIntoTemplate("%{a", rule)).containsExactly("%{a"); |
| 745 | assertThat(substitutePlaceholderIntoTemplate("%{a}}", rule)).containsExactly("a}", "A}") |
| 746 | .inOrder(); |
| 747 | assertThat(substitutePlaceholderIntoTemplate("x%{a}y%{empty}", rule)).isEmpty(); |
| 748 | } |
| 749 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 750 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 751 | public void testOrderIndependentAttribute() throws Exception { |
| 752 | RuleClass ruleClassA = createRuleClassA(); |
| 753 | |
| 754 | List<String> list = Arrays.asList("foo", "bar", "baz"); |
| 755 | Map<String, Object> attributeValues = new LinkedHashMap<>(); |
| 756 | // mandatory values |
| 757 | attributeValues.put("my-string-attr", ""); |
| 758 | attributeValues.put("my-label-attr", "//project"); |
| 759 | attributeValues.put("my-string-attr2", ""); |
| 760 | attributeValues.put("my-labellist-attr", Collections.emptyList()); |
| 761 | // to compare the effect of .orderIndependent() |
| 762 | attributeValues.put("my-stringlist-attr", list); |
| 763 | attributeValues.put("my-sorted-stringlist-attr", list); |
| 764 | |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 765 | Rule rule = createRule(ruleClassA, "testrule", attributeValues, testRuleLocation, NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 766 | AttributeMap attributes = RawAttributeMapper.of(rule); |
| 767 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 768 | assertThat(attributes.get("my-stringlist-attr", Type.STRING_LIST)).isEqualTo(list); |
| 769 | assertThat(attributes.get("my-sorted-stringlist-attr", Type.STRING_LIST)) |
| 770 | .isEqualTo(Arrays.asList("bar", "baz", "foo")); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 771 | } |
| 772 | |
Florian Weikert | ea6c82d | 2016-09-05 12:15:31 +0000 | [diff] [blame] | 773 | private Rule createRule( |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 774 | RuleClass ruleClass, |
| 775 | String name, |
| 776 | Map<String, Object> attributeValues, |
| 777 | Location location, |
| 778 | List<StarlarkThread.CallStackEntry> callstack) |
Florian Weikert | ea6c82d | 2016-09-05 12:15:31 +0000 | [diff] [blame] | 779 | throws LabelSyntaxException, InterruptedException, CannotPrecomputeDefaultsException { |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 780 | Package.Builder pkgBuilder = createDummyPackageBuilder(); |
| 781 | Label ruleLabel; |
| 782 | try { |
| 783 | ruleLabel = pkgBuilder.createLabel(name); |
Lukacs Berki | a643436 | 2015-09-15 13:56:14 +0000 | [diff] [blame] | 784 | } catch (LabelSyntaxException e) { |
Googler | 98eab10 | 2018-10-11 12:28:22 -0700 | [diff] [blame] | 785 | throw new IllegalArgumentException("Rule has illegal label", e); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 786 | } |
Mark Schaller | ee62445 | 2016-01-13 18:41:24 +0000 | [diff] [blame] | 787 | return ruleClass.createRule( |
| 788 | pkgBuilder, |
| 789 | ruleLabel, |
| 790 | new BuildLangTypedAttributeValuesMap(attributeValues), |
| 791 | reporter, |
Mark Schaller | ee62445 | 2016-01-13 18:41:24 +0000 | [diff] [blame] | 792 | location, |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 793 | callstack, |
Greg Estren | 37cd5c4 | 2019-01-30 12:25:50 -0800 | [diff] [blame] | 794 | /*checkThirdPartyRulesHaveLicenses=*/ true); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 795 | } |
| 796 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 797 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 798 | public void testOverrideWithWrongType() { |
jcater | b922677 | 2019-04-29 12:04:52 -0700 | [diff] [blame] | 799 | RuleClass parentRuleClass = createParentRuleClass(); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 800 | |
jcater | b922677 | 2019-04-29 12:04:52 -0700 | [diff] [blame] | 801 | RuleClass.Builder childRuleClassBuilder = |
| 802 | new RuleClass.Builder("child_rule", RuleClassType.NORMAL, false, parentRuleClass); |
| 803 | IllegalStateException e = |
| 804 | assertThrows( |
| 805 | IllegalStateException.class, |
| 806 | () -> childRuleClassBuilder.override(attr("attr", INTEGER))); |
| 807 | assertThat(e) |
| 808 | .hasMessageThat() |
| 809 | .isEqualTo( |
| 810 | "The type of the new attribute 'int' is different from " |
| 811 | + "the original one 'string'."); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 812 | } |
| 813 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 814 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 815 | public void testOverrideWithRightType() { |
| 816 | RuleClass parentRuleClass = createParentRuleClass(); |
| 817 | |
| 818 | RuleClass.Builder childRuleClassBuilder = new RuleClass.Builder( |
| 819 | "child_rule", RuleClassType.NORMAL, false, parentRuleClass); |
| 820 | childRuleClassBuilder.override(attr("attr", STRING)); |
| 821 | } |
| 822 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 823 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 824 | public void testCopyAndOverrideAttribute() throws Exception { |
| 825 | RuleClass parentRuleClass = createParentRuleClass(); |
| 826 | RuleClass childRuleClass = createChildRuleClass(parentRuleClass); |
| 827 | |
| 828 | Map<String, Object> parentValues = new LinkedHashMap<>(); |
| 829 | Map<String, Object> childValues = new LinkedHashMap<>(); |
| 830 | childValues.put("attr", "somevalue"); |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 831 | createRule(parentRuleClass, "parent_rule", parentValues, testRuleLocation, NO_STACK); |
| 832 | createRule(childRuleClass, "child_rule", childValues, testRuleLocation, NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 833 | } |
| 834 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 835 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 836 | public void testCopyAndOverrideAttributeMandatoryMissing() throws Exception { |
| 837 | RuleClass parentRuleClass = createParentRuleClass(); |
| 838 | RuleClass childRuleClass = createChildRuleClass(parentRuleClass); |
| 839 | |
| 840 | Map<String, Object> childValues = new LinkedHashMap<>(); |
| 841 | reporter.removeHandler(failFastHandler); |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 842 | createRule(childRuleClass, "child_rule", childValues, testRuleLocation, NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 843 | |
cpovirk | a4d3da6 | 2019-05-02 14:27:33 -0700 | [diff] [blame] | 844 | assertThat(eventCollector.count()).isSameInstanceAs(1); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 845 | assertContainsEvent("//testpackage:child_rule: missing value for mandatory " |
| 846 | + "attribute 'attr' in 'child_rule' rule"); |
| 847 | } |
| 848 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 849 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 850 | public void testRequiredFragmentInheritance() throws Exception { |
| 851 | RuleClass parentRuleClass = createParentRuleClass(); |
| 852 | RuleClass childRuleClass = createChildRuleClass(parentRuleClass); |
Michael Staib | b51251e | 2015-09-29 23:31:51 +0000 | [diff] [blame] | 853 | assertThat(parentRuleClass.getConfigurationFragmentPolicy().getRequiredConfigurationFragments()) |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 854 | .containsExactly(DummyFragment.class); |
Michael Staib | b51251e | 2015-09-29 23:31:51 +0000 | [diff] [blame] | 855 | assertThat(childRuleClass.getConfigurationFragmentPolicy().getRequiredConfigurationFragments()) |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 856 | .containsExactly(DummyFragment.class); |
| 857 | } |
| 858 | |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 859 | private static RuleClass newRuleClass( |
| 860 | String name, |
gregce | 0503fee | 2020-06-11 09:22:27 -0700 | [diff] [blame] | 861 | boolean starlarkExecutable, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 862 | boolean documented, |
| 863 | boolean publicByDefault, |
| 864 | boolean binaryOutput, |
| 865 | boolean workspaceOnly, |
| 866 | boolean outputsDefaultExecutable, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 867 | boolean isAnalysisTest, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 868 | ImplicitOutputsFunction implicitOutputsFunction, |
John Cater | b3b3e8b | 2019-04-03 09:18:42 -0700 | [diff] [blame] | 869 | TransitionFactory<Rule> transitionFactory, |
cparsons | e2d200f | 2018-03-06 16:15:11 -0800 | [diff] [blame] | 870 | ConfiguredTargetFactory<?, ?, ?> configuredTargetFactory, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 871 | PredicateWithMessage<Rule> validityPredicate, |
| 872 | Predicate<String> preferredDependencyPredicate, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 873 | AdvertisedProviderSet advertisedProviders, |
adonovan | f3a344e8 | 2019-12-11 11:10:11 -0800 | [diff] [blame] | 874 | @Nullable StarlarkFunction configuredTargetFunction, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 875 | Set<Class<?>> allowedConfigurationFragments, |
| 876 | MissingFragmentPolicy missingFragmentPolicy, |
| 877 | boolean supportsConstraintChecking, |
| 878 | Attribute... attributes) { |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 879 | return new RuleClass( |
| 880 | name, |
adonovan | ebb86fc | 2020-03-20 14:57:54 -0700 | [diff] [blame] | 881 | DUMMY_STACK, |
| 882 | /*key=*/ name, |
janakr | 6ff110e | 2018-03-21 21:44:27 -0700 | [diff] [blame] | 883 | RuleClassType.NORMAL, |
gregce | 0503fee | 2020-06-11 09:22:27 -0700 | [diff] [blame] | 884 | /*isStarlark=*/ starlarkExecutable, |
| 885 | /*starlarkTestable=*/ false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 886 | documented, |
| 887 | publicByDefault, |
| 888 | binaryOutput, |
| 889 | workspaceOnly, |
| 890 | outputsDefaultExecutable, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 891 | isAnalysisTest, |
cparsons | 9d40c6b | 2019-02-25 12:24:40 -0800 | [diff] [blame] | 892 | /* hasAnalysisTestTransition=*/ false, |
Googler | c2200fd | 2018-09-14 17:35:59 -0700 | [diff] [blame] | 893 | /* hasFunctionTransitionWhitelist=*/ false, |
gregce | 1d8d6dd | 2019-04-10 09:27:34 -0700 | [diff] [blame] | 894 | /* ignoreLicenses=*/ false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 895 | implicitOutputsFunction, |
Michael Staib | 2a67520 | 2017-03-20 18:06:48 +0000 | [diff] [blame] | 896 | transitionFactory, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 897 | configuredTargetFactory, |
| 898 | validityPredicate, |
| 899 | preferredDependencyPredicate, |
| 900 | advertisedProviders, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 901 | configuredTargetFunction, |
John Cater | 39401a9 | 2020-07-09 10:12:55 -0700 | [diff] [blame^] | 902 | NO_EXTERNAL_BINDINGS, |
| 903 | NO_TOOLCHAINS_TO_REGISTER, |
mstaib | e5538ad | 2017-04-04 18:32:23 +0000 | [diff] [blame] | 904 | /*optionReferenceFunction=*/ RuleClass.NO_OPTION_REFERENCE, |
ajurkowski | 9f2cab5 | 2020-05-12 12:00:24 -0700 | [diff] [blame] | 905 | /*ruleDefinitionEnvironmentLabel=*/ null, |
| 906 | /*ruleDefinitionEnvironmentDigest=*/ null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 907 | new ConfigurationFragmentPolicy.Builder() |
| 908 | .requiresConfigurationFragments(allowedConfigurationFragments) |
| 909 | .setMissingFragmentPolicy(missingFragmentPolicy) |
| 910 | .build(), |
| 911 | supportsConstraintChecking, |
gregce | 4aa059a | 2019-02-26 13:20:47 -0800 | [diff] [blame] | 912 | ThirdPartyLicenseExistencePolicy.USER_CONTROLLABLE, |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 913 | /*requiredToolchains=*/ ImmutableSet.of(), |
jcater | 01bb1f9 | 2019-06-17 12:09:11 -0700 | [diff] [blame] | 914 | /*useToolchainResolution=*/ true, |
John Cater | 099cf2f | 2020-06-11 12:58:36 -0700 | [diff] [blame] | 915 | /*useToolchainTransition=*/ true, |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 916 | /* executionPlatformConstraints= */ ImmutableSet.of(), |
juliexxia | 693048d | 2020-04-01 06:41:42 -0700 | [diff] [blame] | 917 | /* execGroups= */ ImmutableMap.of(), |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 918 | OutputFile.Kind.FILE, |
juliexxia | 1f332e0 | 2018-10-31 14:20:55 -0700 | [diff] [blame] | 919 | ImmutableList.copyOf(attributes), |
| 920 | /* buildSetting= */ null); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 921 | } |
| 922 | |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 923 | private static RuleClass createParentRuleClass() { |
| 924 | return newRuleClass( |
| 925 | "parent_rule", |
| 926 | false, |
| 927 | false, |
| 928 | false, |
| 929 | false, |
| 930 | false, |
| 931 | false, |
cparsons | 55781c9 | 2018-10-17 12:03:08 -0700 | [diff] [blame] | 932 | false, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 933 | ImplicitOutputsFunction.NONE, |
Cal Peyser | 19dda25 | 2017-01-11 23:37:05 +0000 | [diff] [blame] | 934 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 935 | DUMMY_CONFIGURED_TARGET_FACTORY, |
| 936 | PredicatesWithMessage.<Rule>alwaysTrue(), |
| 937 | PREFERRED_DEPENDENCY_PREDICATE, |
Dmitry Lomov | b91d392 | 2017-01-09 20:12:57 +0000 | [diff] [blame] | 938 | AdvertisedProviderSet.EMPTY, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 939 | null, |
Janak Ramakrishnan | 3be65b8 | 2016-05-18 15:53:10 +0000 | [diff] [blame] | 940 | ImmutableSet.<Class<?>>of(DummyFragment.class), |
| 941 | MissingFragmentPolicy.FAIL_ANALYSIS, |
| 942 | true, |
| 943 | attr("attr", STRING).build()); |
| 944 | } |
| 945 | |
| 946 | private static RuleClass createChildRuleClass(RuleClass parentRuleClass) { |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 947 | RuleClass.Builder childRuleClassBuilder = new RuleClass.Builder( |
| 948 | "child_rule", RuleClassType.NORMAL, false, parentRuleClass); |
| 949 | return childRuleClassBuilder.override( |
| 950 | childRuleClassBuilder |
| 951 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 952 | .copy("attr").mandatory()) |
| 953 | .add(attr("tags", STRING_LIST)) |
| 954 | .build(); |
| 955 | } |
| 956 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 957 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 958 | public void testValidityChecker() throws Exception { |
| 959 | RuleClass depClass = new RuleClass.Builder("dep", RuleClassType.NORMAL, false) |
| 960 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 961 | .add(attr("tags", STRING_LIST)) |
| 962 | .build(); |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 963 | final Rule dep1 = createRule(depClass, "dep1", ImmutableMap.of(), testRuleLocation, NO_STACK); |
| 964 | final Rule dep2 = createRule(depClass, "dep2", ImmutableMap.of(), testRuleLocation, NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 965 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 966 | ValidityPredicate checker = |
| 967 | new ValidityPredicate() { |
| 968 | @Override |
| 969 | public String checkValid(Rule from, Rule to) { |
| 970 | assertThat(from.getName()).isEqualTo("top"); |
| 971 | if (to.getName().equals("dep1")) { |
| 972 | return "pear"; |
| 973 | } else if (to.getName().equals("dep2")) { |
| 974 | return null; |
| 975 | } else { |
| 976 | fail("invalid dependency"); |
| 977 | return null; |
| 978 | } |
| 979 | } |
| 980 | }; |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 981 | |
| 982 | RuleClass topClass = new RuleClass.Builder("top", RuleClassType.NORMAL, false) |
| 983 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 984 | .add(attr("tags", STRING_LIST)) |
| 985 | .add(attr("deps", LABEL_LIST).legacyAllowAnyFileType() |
| 986 | .validityPredicate(checker)) |
| 987 | .build(); |
| 988 | |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 989 | Rule topRule = createRule(topClass, "top", ImmutableMap.of(), testRuleLocation, NO_STACK); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 990 | |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 991 | assertThat(topClass.getAttributeByName("deps").getValidityPredicate().checkValid(topRule, dep1)) |
| 992 | .isEqualTo("pear"); |
| 993 | assertThat(topClass.getAttributeByName("deps").getValidityPredicate().checkValid(topRule, dep2)) |
| 994 | .isNull(); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 995 | } |
| 996 | |
| 997 | /** |
| 998 | * Tests structure for making certain rules "preferential choices" for certain files |
| 999 | * under --compile_one_dependency. |
| 1000 | */ |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 1001 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 1002 | public void testPreferredDependencyChecker() throws Exception { |
| 1003 | final String cppFile = "file.cc"; |
| 1004 | final String textFile = "file.txt"; |
| 1005 | |
| 1006 | // Default: not preferred for anything. |
| 1007 | RuleClass defaultClass = new RuleClass.Builder("defaultClass", RuleClassType.NORMAL, false) |
| 1008 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 1009 | .add(attr("tags", STRING_LIST)) |
| 1010 | .build(); |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 1011 | final Rule defaultRule = |
| 1012 | createRule(defaultClass, "defaultRule", ImmutableMap.of(), testRuleLocation, NO_STACK); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 1013 | assertThat(defaultRule.getRuleClassObject().isPreferredDependency(cppFile)).isFalse(); |
| 1014 | assertThat(defaultRule.getRuleClassObject().isPreferredDependency(textFile)).isFalse(); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 1015 | |
| 1016 | // Make a rule that's preferred for C++ sources. |
| 1017 | RuleClass cppClass = new RuleClass.Builder("cppClass", RuleClassType.NORMAL, false) |
| 1018 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 1019 | .add(attr("tags", STRING_LIST)) |
| 1020 | .setPreferredDependencyPredicate(new Predicate<String>() { |
| 1021 | @Override |
| 1022 | public boolean apply(String filename) { |
| 1023 | return filename.endsWith(".cc"); |
| 1024 | } |
| 1025 | }) |
| 1026 | .build(); |
adonovan | 40a737c | 2020-03-11 14:32:19 -0700 | [diff] [blame] | 1027 | final Rule cppRule = |
| 1028 | createRule(cppClass, "cppRule", ImmutableMap.of(), testRuleLocation, NO_STACK); |
lberki | aea56b3 | 2017-05-30 12:35:33 +0200 | [diff] [blame] | 1029 | assertThat(cppRule.getRuleClassObject().isPreferredDependency(cppFile)).isTrue(); |
| 1030 | assertThat(cppRule.getRuleClassObject().isPreferredDependency(textFile)).isFalse(); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 1031 | } |
| 1032 | |
Florian Weikert | 432d198 | 2015-12-01 14:38:06 +0000 | [diff] [blame] | 1033 | @Test |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 1034 | public void testBadRuleClassNames() { |
| 1035 | expectError(RuleClassType.NORMAL, "8abc"); |
Laurent Le Brun | 6ce51e1 | 2015-07-07 11:54:41 +0000 | [diff] [blame] | 1036 | expectError(RuleClassType.NORMAL, "!abc"); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 1037 | expectError(RuleClassType.NORMAL, "a b"); |
| 1038 | } |
| 1039 | |
| 1040 | private void expectError(RuleClassType type, String name) { |
jcater | b922677 | 2019-04-29 12:04:52 -0700 | [diff] [blame] | 1041 | assertThrows(IllegalArgumentException.class, () -> type.checkName(name)); |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 1042 | } |
John Cater | eca2840 | 2017-05-17 21:44:12 +0200 | [diff] [blame] | 1043 | |
| 1044 | @Test |
| 1045 | public void testRequiredToolchains() throws Exception { |
| 1046 | RuleClass.Builder ruleClassBuilder = |
| 1047 | new RuleClass.Builder("ruleClass", RuleClassType.NORMAL, false) |
| 1048 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 1049 | .add(attr("tags", STRING_LIST)); |
| 1050 | |
John Cater | 9a8d16e | 2017-07-05 16:12:07 -0400 | [diff] [blame] | 1051 | ruleClassBuilder.addRequiredToolchains( |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 1052 | Label.parseAbsolute("//toolchain:tc1", ImmutableMap.of()), |
| 1053 | Label.parseAbsolute("//toolchain:tc2", ImmutableMap.of())); |
John Cater | eca2840 | 2017-05-17 21:44:12 +0200 | [diff] [blame] | 1054 | |
| 1055 | RuleClass ruleClass = ruleClassBuilder.build(); |
| 1056 | |
John Cater | 9a8d16e | 2017-07-05 16:12:07 -0400 | [diff] [blame] | 1057 | assertThat(ruleClass.getRequiredToolchains()) |
| 1058 | .containsExactly( |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 1059 | Label.parseAbsolute("//toolchain:tc1", ImmutableMap.of()), |
| 1060 | Label.parseAbsolute("//toolchain:tc2", ImmutableMap.of())); |
John Cater | eca2840 | 2017-05-17 21:44:12 +0200 | [diff] [blame] | 1061 | } |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1062 | |
| 1063 | @Test |
John Cater | 04be3f8 | 2019-11-07 12:20:25 -0800 | [diff] [blame] | 1064 | public void testExecutionPlatformConstraints() throws Exception { |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1065 | RuleClass.Builder ruleClassBuilder = |
| 1066 | new RuleClass.Builder("ruleClass", RuleClassType.NORMAL, false) |
| 1067 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
John Cater | 04be3f8 | 2019-11-07 12:20:25 -0800 | [diff] [blame] | 1068 | .add(attr("tags", STRING_LIST)); |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1069 | |
| 1070 | ruleClassBuilder.addExecutionPlatformConstraints( |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 1071 | Label.parseAbsolute("//constraints:cv1", ImmutableMap.of()), |
| 1072 | Label.parseAbsolute("//constraints:cv2", ImmutableMap.of())); |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1073 | |
| 1074 | RuleClass ruleClass = ruleClassBuilder.build(); |
| 1075 | |
| 1076 | assertThat(ruleClass.getExecutionPlatformConstraints()) |
| 1077 | .containsExactly( |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 1078 | Label.parseAbsolute("//constraints:cv1", ImmutableMap.of()), |
| 1079 | Label.parseAbsolute("//constraints:cv2", ImmutableMap.of())); |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1080 | } |
| 1081 | |
| 1082 | @Test |
| 1083 | public void testExecutionPlatformConstraints_inheritConstraintsFromParent() throws Exception { |
| 1084 | RuleClass parentRuleClass = |
| 1085 | new RuleClass.Builder("$parentRuleClass", RuleClassType.ABSTRACT, false) |
| 1086 | .add(attr("tags", STRING_LIST)) |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1087 | .addExecutionPlatformConstraints( |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 1088 | Label.parseAbsolute("//constraints:cv1", ImmutableMap.of()), |
| 1089 | Label.parseAbsolute("//constraints:cv2", ImmutableMap.of())) |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1090 | .build(); |
| 1091 | |
| 1092 | RuleClass childRuleClass = |
| 1093 | new RuleClass.Builder("childRuleClass", RuleClassType.NORMAL, false, parentRuleClass) |
| 1094 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 1095 | .build(); |
| 1096 | |
| 1097 | assertThat(childRuleClass.getExecutionPlatformConstraints()) |
| 1098 | .containsExactly( |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 1099 | Label.parseAbsolute("//constraints:cv1", ImmutableMap.of()), |
| 1100 | Label.parseAbsolute("//constraints:cv2", ImmutableMap.of())); |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1101 | } |
| 1102 | |
| 1103 | @Test |
| 1104 | public void testExecutionPlatformConstraints_inheritAndAddConstraints() throws Exception { |
| 1105 | RuleClass parentRuleClass = |
| 1106 | new RuleClass.Builder("$parentRuleClass", RuleClassType.ABSTRACT, false) |
| 1107 | .add(attr("tags", STRING_LIST)) |
| 1108 | .build(); |
| 1109 | |
| 1110 | RuleClass.Builder childRuleClassBuilder = |
| 1111 | new RuleClass.Builder("childRuleClass", RuleClassType.NORMAL, false, parentRuleClass) |
| 1112 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1113 | .addExecutionPlatformConstraints( |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 1114 | Label.parseAbsolute("//constraints:cv1", ImmutableMap.of()), |
| 1115 | Label.parseAbsolute("//constraints:cv2", ImmutableMap.of())); |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1116 | |
| 1117 | RuleClass childRuleClass = childRuleClassBuilder.build(); |
| 1118 | |
| 1119 | assertThat(childRuleClass.getExecutionPlatformConstraints()) |
| 1120 | .containsExactly( |
dannark | 90e2b4b | 2018-06-27 13:35:04 -0700 | [diff] [blame] | 1121 | Label.parseAbsolute("//constraints:cv1", ImmutableMap.of()), |
| 1122 | Label.parseAbsolute("//constraints:cv2", ImmutableMap.of())); |
John Cater | ee45c66 | 2018-06-05 11:09:01 -0700 | [diff] [blame] | 1123 | } |
juliexxia | 1f332e0 | 2018-10-31 14:20:55 -0700 | [diff] [blame] | 1124 | |
| 1125 | @Test |
juliexxia | 693048d | 2020-04-01 06:41:42 -0700 | [diff] [blame] | 1126 | public void testExecGroups() throws Exception { |
| 1127 | RuleClass.Builder ruleClassBuilder = |
| 1128 | new RuleClass.Builder("ruleClass", RuleClassType.NORMAL, false) |
| 1129 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 1130 | .add(attr("tags", STRING_LIST)); |
| 1131 | |
| 1132 | Label toolchain = Label.parseAbsoluteUnchecked("//toolchain"); |
| 1133 | Label constraint = Label.parseAbsoluteUnchecked("//constraint"); |
| 1134 | |
| 1135 | ruleClassBuilder.addExecGroups( |
| 1136 | ImmutableMap.of( |
juliexxia | fae8904 | 2020-06-12 12:05:21 -0700 | [diff] [blame] | 1137 | "cherry", ExecGroup.create(ImmutableSet.of(toolchain), ImmutableSet.of(constraint)))); |
juliexxia | 693048d | 2020-04-01 06:41:42 -0700 | [diff] [blame] | 1138 | |
| 1139 | RuleClass ruleClass = ruleClassBuilder.build(); |
| 1140 | |
| 1141 | assertThat(ruleClass.getExecGroups()).hasSize(1); |
juliexxia | fae8904 | 2020-06-12 12:05:21 -0700 | [diff] [blame] | 1142 | assertThat(ruleClass.getExecGroups().get("cherry").requiredToolchains()) |
juliexxia | 693048d | 2020-04-01 06:41:42 -0700 | [diff] [blame] | 1143 | .containsExactly(toolchain); |
juliexxia | fae8904 | 2020-06-12 12:05:21 -0700 | [diff] [blame] | 1144 | assertThat(ruleClass.getExecGroups().get("cherry").execCompatibleWith()) |
juliexxia | 693048d | 2020-04-01 06:41:42 -0700 | [diff] [blame] | 1145 | .containsExactly(constraint); |
| 1146 | } |
| 1147 | |
| 1148 | @Test |
juliexxia | 1f332e0 | 2018-10-31 14:20:55 -0700 | [diff] [blame] | 1149 | public void testBuildSetting_createsDefaultAttribute() { |
| 1150 | RuleClass labelFlag = |
| 1151 | new RuleClass.Builder("label_flag", RuleClassType.NORMAL, false) |
| 1152 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 1153 | .add(attr("tags", STRING_LIST)) |
| 1154 | .setBuildSetting(new BuildSetting(true, LABEL)) |
| 1155 | .build(); |
| 1156 | RuleClass stringSetting = |
| 1157 | new RuleClass.Builder("string_setting", RuleClassType.NORMAL, false) |
| 1158 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 1159 | .add(attr("tags", STRING_LIST)) |
| 1160 | .setBuildSetting(new BuildSetting(false, STRING)) |
| 1161 | .build(); |
| 1162 | |
gregce | 74d84d4 | 2020-04-17 10:02:03 -0700 | [diff] [blame] | 1163 | assertThat(labelFlag.hasAttr(STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, LABEL)).isTrue(); |
| 1164 | assertThat(stringSetting.hasAttr(STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, STRING)).isTrue(); |
juliexxia | 1f332e0 | 2018-10-31 14:20:55 -0700 | [diff] [blame] | 1165 | } |
| 1166 | |
| 1167 | @Test |
| 1168 | public void testBuildSetting_doesNotCreateDefaultAttributeIfNotBuildSetting() { |
| 1169 | RuleClass stringSetting = |
| 1170 | new RuleClass.Builder("non_build_setting", RuleClassType.NORMAL, false) |
| 1171 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 1172 | .add(attr("tags", STRING_LIST)) |
| 1173 | .build(); |
| 1174 | |
gregce | 74d84d4 | 2020-04-17 10:02:03 -0700 | [diff] [blame] | 1175 | assertThat(stringSetting.hasAttr(STARLARK_BUILD_SETTING_DEFAULT_ATTR_NAME, LABEL)).isFalse(); |
juliexxia | 1f332e0 | 2018-10-31 14:20:55 -0700 | [diff] [blame] | 1176 | } |
michajlo | b839a51 | 2020-03-11 10:04:23 -0700 | [diff] [blame] | 1177 | |
| 1178 | @Test |
| 1179 | public void testBuildTooManyAttributesRejected() { |
| 1180 | RuleClass.Builder builder = |
gregce | 0503fee | 2020-06-11 09:22:27 -0700 | [diff] [blame] | 1181 | new RuleClass.Builder("myclass", RuleClassType.NORMAL, /*starlark=*/ false) |
michajlo | b839a51 | 2020-03-11 10:04:23 -0700 | [diff] [blame] | 1182 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 1183 | .add(attr("tags", STRING_LIST)); |
michajlo | 7475b77 | 2020-03-12 15:10:11 -0700 | [diff] [blame] | 1184 | for (int i = 0; i < 200; i++) { |
michajlo | b839a51 | 2020-03-11 10:04:23 -0700 | [diff] [blame] | 1185 | builder.add(attr("attr" + i, STRING)); |
| 1186 | } |
| 1187 | |
| 1188 | IllegalArgumentException expected = |
| 1189 | assertThrows(IllegalArgumentException.class, builder::build); |
| 1190 | |
| 1191 | assertThat(expected) |
| 1192 | .hasMessageThat() |
michajlo | 7475b77 | 2020-03-12 15:10:11 -0700 | [diff] [blame] | 1193 | .isEqualTo("Rule class myclass declared too many attributes (201 > 200)"); |
michajlo | b839a51 | 2020-03-11 10:04:23 -0700 | [diff] [blame] | 1194 | } |
michajlo | 0a89cef | 2020-04-06 12:04:12 -0700 | [diff] [blame] | 1195 | |
| 1196 | @Test |
| 1197 | public void testBuildTooLongAttributeNameRejected() { |
| 1198 | IllegalArgumentException expected = |
| 1199 | assertThrows( |
| 1200 | IllegalArgumentException.class, |
| 1201 | () -> |
gregce | 0503fee | 2020-06-11 09:22:27 -0700 | [diff] [blame] | 1202 | new RuleClass.Builder("myclass", RuleClassType.NORMAL, /*starlark=*/ false) |
michajlo | 0a89cef | 2020-04-06 12:04:12 -0700 | [diff] [blame] | 1203 | .factory(DUMMY_CONFIGURED_TARGET_FACTORY) |
| 1204 | .add(attr("tags", STRING_LIST)) |
| 1205 | .add(attr(Strings.repeat("x", 150), STRING)) |
| 1206 | .build()); |
| 1207 | |
| 1208 | assertThat(expected) |
| 1209 | .hasMessageThat() |
| 1210 | .matches("Attribute myclass\\.x{150}'s name is too long \\(150 > 128\\)"); |
| 1211 | } |
Ulf Adams | 83763ee | 2015-05-04 15:36:12 +0000 | [diff] [blame] | 1212 | } |