aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test
diff options
context:
space:
mode:
authorGravatar Ulf Adams <ulfjack@google.com>2015-05-04 12:05:57 +0000
committerGravatar Damien Martin-Guillerez <dmarting@google.com>2015-05-04 17:51:54 +0000
commitb313a9750d77ea4ccd3cb591131e2311486cb11a (patch)
tree990b298339cae32fe0fce5649c3669de3cb1966b /src/test
parent208df987a0d5a27370691f93b34a5f70f6982cbe (diff)
Open source a few more analysis tests.
-- MOS_MIGRATED_REVID=92715161
Diffstat (limited to 'src/test')
-rw-r--r--src/test/java/BUILD19
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/ConfiguredAttributeMapperTest.java196
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/select/AbstractAttributeMapperTest.java146
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/select/AggregatingAttributeMapperTest.java155
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/select/ConfiguredAttributeMapperCommonTest.java36
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/select/NonconfigurableAttributeMapperTest.java52
-rw-r--r--src/test/java/com/google/devtools/build/lib/analysis/select/RawAttributeMapperTest.java149
-rw-r--r--src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java168
8 files changed, 921 insertions, 0 deletions
diff --git a/src/test/java/BUILD b/src/test/java/BUILD
index 7eed6d21e8..ef8e053b0a 100644
--- a/src/test/java/BUILD
+++ b/src/test/java/BUILD
@@ -293,6 +293,25 @@ java_test(
)
java_test(
+ name = "analysis_select_test",
+ srcs = glob([
+ "com/google/devtools/build/lib/analysis/select/*.java",
+ ]),
+ args = ["com.google.devtools.build.lib.AllTests"],
+ deps = [
+ ":actions_testutil",
+ ":analysis_testutil",
+ ":foundations_testutil",
+ ":test_runner",
+ ":testutil",
+ "//src/main/java:bazel-core",
+ "//third_party:guava",
+ "//third_party:junit4",
+ "//third_party:truth",
+ ],
+)
+
+java_test(
name = "analysis_test",
srcs = glob([
"com/google/devtools/build/lib/analysis/*.java",
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/ConfiguredAttributeMapperTest.java b/src/test/java/com/google/devtools/build/lib/analysis/ConfiguredAttributeMapperTest.java
new file mode 100644
index 0000000000..3a854c5f42
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/ConfiguredAttributeMapperTest.java
@@ -0,0 +1,196 @@
+// Copyright 2015 Google Inc. 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.devtools.build.lib.testutil.MoreAsserts.assertSameContents;
+
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.analysis.config.CompilationMode;
+import com.google.devtools.build.lib.analysis.util.BuildViewTestCase;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.AttributeMap;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.syntax.Label;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Unit tests for {@link ConfiguredAttributeMapper}.
+ *
+ * <p>This is distinct from {@link
+ * com.google.devtools.build.lib.analysis.select.ConfiguredAttributeMapperCommonTest} because the
+ * latter needs to inherit from {@link
+ * com.google.devtools.build.lib.analysis.select.AbstractAttributeMapperTest} to run tests common to
+ * all attribute mappers.
+ */
+public class ConfiguredAttributeMapperTest extends BuildViewTestCase {
+
+ /**
+ * Returns a ConfiguredAttributeMapper bound to the given rule with the target configuration.
+ */
+ private ConfiguredAttributeMapper getMapper(String label) throws Exception {
+ return ConfiguredAttributeMapper.of(
+ (RuleConfiguredTarget) getConfiguredTarget(label));
+ }
+
+ private void writeConfigRules() throws Exception {
+ scratch.file("conditions/BUILD",
+ "config_setting(",
+ " name = 'a',",
+ " values = {'compilation_mode': 'opt'})",
+ "config_setting(",
+ " name = 'b',",
+ " values = {'compilation_mode': 'dbg'})");
+ }
+
+ /**
+ * Tests that {@link ConfiguredAttributeMapper#get} only gets the configuration-appropriate
+ * value.
+ */
+ public void testGetAttribute() throws Exception {
+ writeConfigRules();
+ scratch.file("a/BUILD",
+ "genrule(",
+ " name = 'gen',",
+ " srcs = [],",
+ " outs = ['out'],",
+ " cmd = select({",
+ " '//conditions:a': 'a command',",
+ " '//conditions:b': 'b command',",
+ " '" + Type.Selector.DEFAULT_CONDITION_KEY + "': 'default command',",
+ " }))");
+
+ useConfiguration("-c", "opt");
+ assertEquals("a command", getMapper("//a:gen").get("cmd", Type.STRING));
+
+ useConfiguration("-c", "dbg");
+ assertEquals("b command", getMapper("//a:gen").get("cmd", Type.STRING));
+
+ useConfiguration("-c", "fastbuild");
+ assertEquals("default command", getMapper("//a:gen").get("cmd", Type.STRING));
+ }
+
+ /**
+ * Tests that label visitation only travels down configuration-appropriate paths.
+ */
+ public void testLabelVisitation() throws Exception {
+ writeConfigRules();
+ scratch.file("a/BUILD",
+ "sh_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.sh'],",
+ " deps = select({",
+ " '//conditions:a': [':adep'],",
+ " '//conditions:b': [':bdep'],",
+ " '" + Type.Selector.DEFAULT_CONDITION_KEY + "': [':defaultdep'],",
+ " }))",
+ "sh_library(",
+ " name = 'adep',",
+ " srcs = ['adep.sh'])",
+ "sh_library(",
+ " name = 'bdep',",
+ " srcs = ['bdep.sh'])",
+ "sh_library(",
+ " name = 'defaultdep',",
+ " srcs = ['defaultdep.sh'])");
+
+ final List<Label> visitedLabels = new ArrayList<>();
+ AttributeMap.AcceptsLabelAttribute testVisitor =
+ new AttributeMap.AcceptsLabelAttribute() {
+ @Override
+ public void acceptLabelAttribute(Label label, Attribute attribute) {
+ if (label.toString().contains("//a:")) { // Ignore implicit common dependencies.
+ visitedLabels.add(label);
+ }
+ }
+ };
+
+ final Label binSrc = Label.parseAbsolute("//a:bin.sh");
+
+ useConfiguration("-c", "opt");
+ getMapper("//a:bin").visitLabels(testVisitor);
+ assertSameContents(ImmutableList.of(binSrc, Label.parseAbsolute("//a:adep")), visitedLabels);
+
+ visitedLabels.clear();
+ useConfiguration("-c", "dbg");
+ getMapper("//a:bin").visitLabels(testVisitor);
+ assertSameContents(ImmutableList.of(binSrc, Label.parseAbsolute("//a:bdep")), visitedLabels);
+
+ visitedLabels.clear();
+ useConfiguration("-c", "fastbuild");
+ getMapper("//a:bin").visitLabels(testVisitor);
+ assertSameContents(
+ ImmutableList.of(binSrc, Label.parseAbsolute("//a:defaultdep")), visitedLabels);
+ }
+
+ /**
+ * Tests that for configurable attributes where the *values* are evaluated in different
+ * configurations, the configuration checking still uses the original configuration.
+ */
+ public void testConfigurationTransitions() throws Exception {
+ writeConfigRules();
+ scratch.file("a/BUILD",
+ "genrule(",
+ " name = 'gen',",
+ " srcs = [],",
+ " outs = ['out'],",
+ " cmd = 'nothing',",
+ " tools = select({",
+ " '//conditions:a': [':adep'],",
+ " '//conditions:b': [':bdep'],",
+ " '" + Type.Selector.DEFAULT_CONDITION_KEY + "': [':defaultdep'],",
+ " }))",
+ "sh_binary(",
+ " name = 'adep',",
+ " srcs = ['adep.sh'])",
+ "sh_binary(",
+ " name = 'bdep',",
+ " srcs = ['bdep.sh'])",
+ "sh_binary(",
+ " name = 'defaultdep',",
+ " srcs = ['defaultdep.sh'])");
+ useConfiguration("-c", "dbg");
+
+ // Target configuration is in dbg mode, so we should match //conditions:b:
+ assertSameContents(
+ ImmutableList.of(Label.parseAbsolute("//a:bdep")),
+ getMapper("//a:gen").get("tools", Type.LABEL_LIST));
+
+ // Verify the "tools" dep uses a different configuration that's not also in "dbg":
+ assertEquals(Attribute.ConfigurationTransition.HOST,
+ getTarget("//a:gen").getAssociatedRule().getRuleClassObject()
+ .getAttributeByName("tools").getConfigurationTransition());
+ assertEquals(CompilationMode.OPT, getHostConfiguration().getCompilationMode());
+ }
+
+ public void testConcatenatedSelects() throws Exception {
+ scratch.file("hello/BUILD",
+ "config_setting(name = 'a', values = {'define': 'foo=a'})",
+ "config_setting(name = 'b', values = {'define': 'foo=b'})",
+ "config_setting(name = 'c', values = {'define': 'bar=c'})",
+ "config_setting(name = 'd', values = {'define': 'bar=d'})",
+ "genrule(",
+ " name = 'gen',",
+ " srcs = select({':a': ['a.in'], ':b': ['b.in']})",
+ " + select({':c': ['c.in'], ':d': ['d.in']}),",
+ " outs = ['out'],",
+ " cmd = 'nothing',",
+ ")");
+ useConfiguration("--define", "foo=a", "--define", "bar=d");
+ assertSameContents(
+ ImmutableList.of(Label.parseAbsolute("//hello:a.in"), Label.parseAbsolute("//hello:d.in")),
+ getMapper("//hello:gen").get("srcs", Type.LABEL_LIST));
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/select/AbstractAttributeMapperTest.java b/src/test/java/com/google/devtools/build/lib/analysis/select/AbstractAttributeMapperTest.java
new file mode 100644
index 0000000000..f15d1a6a6c
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/select/AbstractAttributeMapperTest.java
@@ -0,0 +1,146 @@
+// Copyright 2015 Google Inc. 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.select;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.devtools.build.lib.events.util.EventCollectionApparatus;
+import com.google.devtools.build.lib.packages.AbstractAttributeMapper;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.AttributeContainer;
+import com.google.devtools.build.lib.packages.AttributeMap;
+import com.google.devtools.build.lib.packages.Package;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.RuleClass;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.packages.util.PackageFactoryApparatus;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.build.lib.testutil.FoundationTestCase;
+import com.google.devtools.build.lib.testutil.MoreAsserts;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.lib.vfs.Path;
+
+import java.util.List;
+
+/**
+ * Unit tests for {@link AbstractAttributeMapper}.
+ */
+public class AbstractAttributeMapperTest extends FoundationTestCase {
+
+ private Package pkg;
+ protected Rule rule;
+ protected AbstractAttributeMapper mapper;
+
+ private static class TestMapper extends AbstractAttributeMapper {
+ public TestMapper(Package pkg, RuleClass ruleClass, Label ruleLabel,
+ AttributeContainer attributes) {
+ super(pkg, ruleClass, ruleLabel, attributes);
+ }
+ }
+
+ protected Rule createRule(String pkgPath, String ruleName, String... ruleDef) throws Exception {
+ Scratch scratch = new Scratch();
+ EventCollectionApparatus events = new EventCollectionApparatus();
+ PackageFactoryApparatus packages = new PackageFactoryApparatus(events, scratch);
+
+ Path buildFile = scratch.file(pkgPath + "/BUILD", ruleDef);
+ pkg = packages.createPackage(pkgPath, buildFile);
+ return pkg.getRule(ruleName);
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ rule = createRule("x", "myrule",
+ "cc_binary(name = 'myrule',",
+ " srcs = ['a', 'b', 'c'])");
+ RuleClass ruleClass = rule.getRuleClassObject();
+ mapper = new TestMapper(pkg, ruleClass, rule.getLabel(), rule.getAttributeContainer());
+ }
+
+ public void testRuleProperties() throws Exception {
+ assertEquals(rule.getName(), mapper.getName());
+ assertEquals(rule.getLabel(), mapper.getLabel());
+ }
+
+ public void testPackageDefaultProperties() throws Exception {
+ assertEquals(pkg.getDefaultHdrsCheck(), mapper.getPackageDefaultHdrsCheck());
+ assertEquals(pkg.getDefaultTestOnly(), mapper.getPackageDefaultTestOnly());
+ assertEquals(pkg.getDefaultDeprecation(), mapper.getPackageDefaultDeprecation());
+ }
+
+ public void testAttributeTypeChecking() throws Exception {
+ // Good typing:
+ mapper.get("srcs", Type.LABEL_LIST);
+
+ // Bad typing:
+ try {
+ mapper.get("srcs", Type.BOOLEAN);
+ fail("Expected type mismatch to trigger an exception");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+
+ // Unknown attribute:
+ try {
+ mapper.get("nonsense", Type.BOOLEAN);
+ fail("Expected non-existent type to trigger an exception");
+ } catch (IllegalArgumentException e) {
+ // Expected.
+ }
+ }
+
+ public void testGetAttributeType() throws Exception {
+ assertEquals(Type.LABEL_LIST, mapper.getAttributeType("srcs"));
+ assertNull(mapper.getAttributeType("nonsense"));
+ }
+
+ public void testGetAttributeDefinition() {
+ assertEquals("srcs", mapper.getAttributeDefinition("srcs").getName());
+ assertNull(mapper.getAttributeDefinition("nonsense"));
+ }
+
+ public void testIsAttributeExplicitlySpecified() throws Exception {
+ assertTrue(mapper.isAttributeValueExplicitlySpecified("srcs"));
+ assertFalse(mapper.isAttributeValueExplicitlySpecified("deps"));
+ assertFalse(mapper.isAttributeValueExplicitlySpecified("nonsense"));
+ }
+
+ protected static class VisitationRecorder implements AttributeMap.AcceptsLabelAttribute {
+ public List<String> labelsVisited = Lists.newArrayList();
+ @Override
+ public void acceptLabelAttribute(Label label, Attribute attribute) {
+ if (attribute.getName().equals("srcs")) {
+ labelsVisited.add(label.toString());
+ }
+ }
+ }
+
+ public void testVisitation() throws Exception {
+ VisitationRecorder recorder = new VisitationRecorder();
+ mapper.visitLabels(recorder);
+ MoreAsserts.assertSameContents(
+ ImmutableList.of("//x:a", "//x:b", "//x:c"), recorder.labelsVisited);
+ }
+
+ public void testComputedDefault() throws Exception {
+ // Should return a valid ComputedDefault instance since this is a computed default:
+ assertThat(mapper.getComputedDefault("$stl", Type.LABEL))
+ .isInstanceOf(Attribute.ComputedDefault.class);
+ // Should return null since this *isn't* a computed default:
+ assertNull(mapper.getComputedDefault("srcs", Type.LABEL_LIST));
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/select/AggregatingAttributeMapperTest.java b/src/test/java/com/google/devtools/build/lib/analysis/select/AggregatingAttributeMapperTest.java
new file mode 100644
index 0000000000..e894939f62
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/select/AggregatingAttributeMapperTest.java
@@ -0,0 +1,155 @@
+// Copyright 2015 Google Inc. 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.select;
+
+import static com.google.devtools.build.lib.testutil.MoreAsserts.assertSameContents;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.build.lib.testutil.TestConstants;
+
+/**
+ * Unit tests for {@link AggregatingAttributeMapper}.
+ */
+public class AggregatingAttributeMapperTest extends AbstractAttributeMapperTest {
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ // Run AbstractAttributeMapper tests through an AggregatingAttributeMapper.
+ mapper = AggregatingAttributeMapper.of(rule);
+ }
+
+ /**
+ * Tests that {@link AggregatingAttributeMapper#visitAttribute} returns an
+ * attribute's sole value when declared directly (i.e. not as a configurable dict).
+ */
+ public void testGetPossibleValuesDirectAttribute() throws Exception {
+ Rule rule = createRule("a", "myrule",
+ "sh_binary(name = 'myrule',",
+ " srcs = ['a.sh'])");
+ assertSameContents(
+ ImmutableList.of(ImmutableList.of(Label.create("a", "a.sh"))),
+ AggregatingAttributeMapper.of(rule).visitAttribute("srcs", Type.LABEL_LIST));
+ }
+
+ /**
+ * Tests that {@link AggregatingAttributeMapper#visitAttribute} returns
+ * every possible value that a configurable attribute can resolve to.
+ */
+ public void testGetPossibleValuesConfigurableAttribute() throws Exception {
+ Rule rule = createRule("a", "myrule",
+ "sh_binary(name = 'myrule',",
+ " srcs = select({",
+ " '//conditions:a': ['a.sh'],",
+ " '//conditions:b': ['b.sh'],",
+ " '" + Type.Selector.DEFAULT_CONDITION_KEY + "': ['default.sh'],",
+ " }))");
+ assertSameContents(
+ ImmutableList.of(
+ ImmutableList.of(Label.create("a", "a.sh")),
+ ImmutableList.of(Label.create("a", "b.sh")),
+ ImmutableList.of(Label.create("a", "default.sh"))),
+ AggregatingAttributeMapper.of(rule).visitAttribute("srcs", Type.LABEL_LIST));
+ }
+
+ public void testGetPossibleValuesWithConcatenatedSelects() throws Exception {
+ Rule rule = createRule("a", "myrule",
+ "sh_binary(name = 'myrule',",
+ " srcs = select({",
+ " '//conditions:a1': ['a1.sh'],",
+ " '//conditions:b1': ['b1.sh']})",
+ " + select({",
+ " '//conditions:a2': ['a2.sh'],",
+ " '//conditions:b2': ['b2.sh']})",
+ " )");
+ assertSameContents(
+ ImmutableList.of(
+ ImmutableList.of(Label.create("a", "a1.sh"), Label.create("a", "a2.sh")),
+ ImmutableList.of(Label.create("a", "a1.sh"), Label.create("a", "b2.sh")),
+ ImmutableList.of(Label.create("a", "b1.sh"), Label.create("a", "a2.sh")),
+ ImmutableList.of(Label.create("a", "b1.sh"), Label.create("a", "b2.sh"))),
+ AggregatingAttributeMapper.of(rule).visitAttribute("srcs", Type.LABEL_LIST));
+ }
+
+ /**
+ * Tests that, on rule visitation, {@link AggregatingAttributeMapper} visits *every* possible
+ * value in a configurable attribute (including configuration key labels).
+ */
+ public void testVisitationConfigurableAttribute() throws Exception {
+ Rule rule = createRule("a", "myrule",
+ "sh_binary(name = 'myrule',",
+ " srcs = select({",
+ " '//conditions:a': ['a.sh'],",
+ " '//conditions:b': ['b.sh'],",
+ " '" + Type.Selector.DEFAULT_CONDITION_KEY + "': ['default.sh'],",
+ " }))");
+
+ VisitationRecorder recorder = new VisitationRecorder();
+ AggregatingAttributeMapper.of(rule).visitLabels(recorder);
+ assertSameContents(
+ ImmutableList.of(
+ "//a:a.sh", "//a:b.sh", "//a:default.sh", "//conditions:a", "//conditions:b"),
+ recorder.labelsVisited);
+ }
+
+ public void testGetReachableLabels() throws Exception {
+ Rule rule = createRule("x", "main",
+ "cc_binary(",
+ " name = 'main',",
+ " srcs = select({",
+ " '//conditions:a': ['a.cc'],",
+ " '//conditions:b': ['b.cc']})",
+ " + ",
+ " ['always.cc']",
+ " + ",
+ " select({",
+ " '//conditions:c': ['c.cc'],",
+ " '//conditions:d': ['d.cc'],",
+ " '" + Type.Selector.DEFAULT_CONDITION_KEY + "': ['default.cc'],",
+ " }))");
+
+ ImmutableList<Label> valueLabels = ImmutableList.of(
+ Label.create("x", "a.cc"), Label.create("x", "b.cc"), Label.create("x", "always.cc"),
+ Label.create("x", "c.cc"), Label.create("x", "d.cc"), Label.create("x", "default.cc"));
+ ImmutableList<Label> keyLabels = ImmutableList.of(
+ Label.create("conditions", "a"), Label.create("conditions", "b"),
+ Label.create("conditions", "c"), Label.create("conditions", "d"));
+
+ AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
+ assertSameContents(
+ Iterables.concat(valueLabels, keyLabels),
+ mapper.getReachableLabels("srcs", true));
+ assertSameContents(valueLabels, mapper.getReachableLabels("srcs", false));
+ }
+
+ public void testDuplicateCheckOnNullValues() throws Exception {
+ if (TestConstants.THIS_IS_BAZEL) {
+ return;
+ }
+ Rule rule = createRule("x", "main",
+ "java_binary(",
+ " name = 'main',",
+ " srcs = ['main.java'])");
+ AggregatingAttributeMapper mapper = AggregatingAttributeMapper.of(rule);
+ Attribute launcherAttribute = mapper.getAttributeDefinition("launcher");
+ assertNull(mapper.get(launcherAttribute.getName(), launcherAttribute.getType()));
+ assertSameContents(ImmutableList.of(), mapper.checkForDuplicateLabels(launcherAttribute));
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/select/ConfiguredAttributeMapperCommonTest.java b/src/test/java/com/google/devtools/build/lib/analysis/select/ConfiguredAttributeMapperCommonTest.java
new file mode 100644
index 0000000000..041cdbe362
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/select/ConfiguredAttributeMapperCommonTest.java
@@ -0,0 +1,36 @@
+// Copyright 2015 Google Inc. 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.select;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.analysis.ConfiguredAttributeMapper;
+import com.google.devtools.build.lib.analysis.config.ConfigMatchingProvider;
+import com.google.devtools.build.lib.packages.AbstractAttributeMapper;
+
+/**
+ * Tests that {@link ConfiguredAttributeMapper} fulfills all behavior expected
+ * of {@link AbstractAttributeMapper}.
+ *
+ * <p>This is distinct from {@link
+ * com.google.devtools.build.lib.analysis.ConfiguredAttributeMapperTest} because the latter needs to
+ * inherit from {@link com.google.devtools.build.lib.analysis.util.BuildViewTestCase} to run tests
+ * with build configurations.
+ */
+public class ConfiguredAttributeMapperCommonTest extends AbstractAttributeMapperTest {
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ mapper = ConfiguredAttributeMapper.of(rule, ImmutableSet.<ConfigMatchingProvider>of());
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/select/NonconfigurableAttributeMapperTest.java b/src/test/java/com/google/devtools/build/lib/analysis/select/NonconfigurableAttributeMapperTest.java
new file mode 100644
index 0000000000..01ef88d58e
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/select/NonconfigurableAttributeMapperTest.java
@@ -0,0 +1,52 @@
+// Copyright 2015 Google Inc. 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.select;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
+import com.google.devtools.build.lib.packages.Type;
+
+/**
+ * Unit tests for {@link NonconfigurableAttributeMapper}.
+ */
+public class NonconfigurableAttributeMapperTest extends AbstractAttributeMapperTest {
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ rule = createRule("x", "myrule",
+ "cc_binary(",
+ " name = 'myrule',",
+ " srcs = ['a', 'b', 'c'],",
+ " linkstatic = 1,",
+ " deprecation = \"this rule is deprecated!\")");
+ }
+
+ public void testGetNonconfigurableAttribute() throws Exception {
+ assertEquals("this rule is deprecated!",
+ NonconfigurableAttributeMapper.of(rule).get("deprecation", Type.STRING));
+ }
+
+ public void testGetConfigurableAttribute() throws Exception {
+ try {
+ NonconfigurableAttributeMapper.of(rule).get("linkstatic", Type.BOOLEAN);
+ fail("Expected NonconfigurableAttributeMapper to fail on a configurable attribute type");
+ } catch (IllegalStateException e) {
+ // Expected outcome.
+ assertThat(e).hasMessage(
+ "Attribute 'linkstatic' is potentially configurable - not allowed here");
+ }
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/analysis/select/RawAttributeMapperTest.java b/src/test/java/com/google/devtools/build/lib/analysis/select/RawAttributeMapperTest.java
new file mode 100644
index 0000000000..b1c02d4281
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/analysis/select/RawAttributeMapperTest.java
@@ -0,0 +1,149 @@
+// Copyright 2015 Google Inc. 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.select;
+
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.devtools.build.lib.testutil.MoreAsserts.assertSameContents;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.packages.Attribute;
+import com.google.devtools.build.lib.packages.AttributeMap;
+import com.google.devtools.build.lib.packages.RawAttributeMapper;
+import com.google.devtools.build.lib.packages.Rule;
+import com.google.devtools.build.lib.packages.Type;
+import com.google.devtools.build.lib.syntax.Label;
+
+import java.util.List;
+
+/**
+ * Unit tests for {@link RawAttributeMapper}.
+ */
+public class RawAttributeMapperTest extends AbstractAttributeMapperTest {
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ // Run AbstractAttributeMapper tests through a RawAttributeMapper.
+ mapper = RawAttributeMapper.of(rule);
+ }
+
+ private Rule setupGenRule() throws Exception {
+ return createRule("x", "myrule",
+ "sh_binary(",
+ " name = 'myrule',",
+ " srcs = select({",
+ " '//conditions:a': ['a.sh'],",
+ " '//conditions:b': ['b.sh'],",
+ " '" + Type.Selector.DEFAULT_CONDITION_KEY + "': ['default.sh'],",
+ " }),",
+ " data = [ ':data_a', ':data_b' ])");
+ }
+
+ public void testGetAttribute() throws Exception {
+ RawAttributeMapper rawMapper = RawAttributeMapper.of(setupGenRule());
+ List<Label> value = rawMapper.get("data", Type.LABEL_LIST);
+ assertNotNull(value);
+ assertThat(value).containsExactly(Label.create("x", "data_a"), Label.create("x", "data_b"));
+
+ // Configurable attribute: trying to directly access from a RawAttributeMapper throws a
+ // type mismatch exception.
+ try {
+ rawMapper.get("srcs", Type.LABEL_LIST);
+ fail("Expected srcs lookup to fail since the returned type is a SelectorList and not a list");
+ } catch (IllegalArgumentException e) {
+ assertThat(e.getCause().getMessage())
+ .contains("SelectorList cannot be cast to java.util.List");
+ }
+ }
+
+ @Override
+ public void testGetAttributeType() throws Exception {
+ RawAttributeMapper rawMapper = RawAttributeMapper.of(setupGenRule());
+ assertEquals(Type.LABEL_LIST, rawMapper.getAttributeType("data")); // not configurable
+ assertEquals(Type.LABEL_LIST, rawMapper.getAttributeType("srcs")); // configurable
+ }
+
+ public void testConfigurabilityCheck() throws Exception {
+ RawAttributeMapper rawMapper = RawAttributeMapper.of(setupGenRule());
+ assertFalse(rawMapper.isConfigurable("data", Type.LABEL_LIST));
+ assertTrue(rawMapper.isConfigurable("srcs", Type.LABEL_LIST));
+ }
+
+ /**
+ * Tests that RawAttributeMapper can't handle label visitation with configurable attributes.
+ */
+ public void testVisitLabels() throws Exception {
+ RawAttributeMapper rawMapper = RawAttributeMapper.of(setupGenRule());
+ try {
+ rawMapper.visitLabels(new AttributeMap.AcceptsLabelAttribute() {
+ @Override
+ public void acceptLabelAttribute(Label label, Attribute attribute) {
+ // Nothing to do.
+ }
+ });
+ fail("Expected label visitation to fail since one attribute is configurable");
+ } catch (IllegalArgumentException e) {
+ assertThat(e.getCause().getMessage())
+ .contains("SelectorList cannot be cast to java.util.List");
+ }
+ }
+
+ public void testGetConfigurabilityKeys() throws Exception {
+ RawAttributeMapper rawMapper = RawAttributeMapper.of(setupGenRule());
+ assertSameContents(
+ ImmutableSet.of(
+ Label.parseAbsolute("//conditions:a"),
+ Label.parseAbsolute("//conditions:b"),
+ Label.parseAbsolute("//conditions:default")),
+ rawMapper.getConfigurabilityKeys("srcs", Type.LABEL_LIST));
+ assertThat(rawMapper.getConfigurabilityKeys("data", Type.LABEL_LIST)).isEmpty();
+ }
+
+ public void testGetMergedValues() throws Exception {
+ Rule rule = createRule("x", "myrule",
+ "sh_binary(",
+ " name = 'myrule',",
+ " srcs = select({",
+ " '//conditions:a': ['a.sh', 'b.sh'],",
+ " '//conditions:b': ['b.sh', 'c.sh'],",
+ " }))");
+ RawAttributeMapper rawMapper = RawAttributeMapper.of(rule);
+ assertThat(rawMapper.getMergedValues("srcs", Type.LABEL_LIST)).containsExactly(
+ Label.parseAbsolute("//x:a.sh"),
+ Label.parseAbsolute("//x:b.sh"),
+ Label.parseAbsolute("//x:c.sh"))
+ .inOrder();
+ }
+
+ public void testMergedValuesWithConcatenatedSelects() throws Exception {
+ Rule rule = createRule("x", "myrule",
+ "sh_binary(",
+ " name = 'myrule',",
+ " srcs = select({",
+ " '//conditions:a1': ['a1.sh'],",
+ " '//conditions:b1': ['b1.sh', 'another_b1.sh']})",
+ " + select({",
+ " '//conditions:a2': ['a2.sh'],",
+ " '//conditions:b2': ['b2.sh']})",
+ " )");
+ RawAttributeMapper rawMapper = RawAttributeMapper.of(rule);
+ assertThat(rawMapper.getMergedValues("srcs", Type.LABEL_LIST)).containsExactly(
+ Label.parseAbsolute("//x:a1.sh"),
+ Label.parseAbsolute("//x:b1.sh"),
+ Label.parseAbsolute("//x:another_b1.sh"),
+ Label.parseAbsolute("//x:a2.sh"),
+ Label.parseAbsolute("//x:b2.sh"))
+ .inOrder();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java b/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java
new file mode 100644
index 0000000000..5370cead05
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/packages/util/PackageFactoryApparatus.java
@@ -0,0 +1,168 @@
+// Copyright 2007-2015 Google Inc. 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.packages.util;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.events.Reporter;
+import com.google.devtools.build.lib.events.util.EventCollectionApparatus;
+import com.google.devtools.build.lib.packages.CachingPackageLocator;
+import com.google.devtools.build.lib.packages.ConstantRuleVisibility;
+import com.google.devtools.build.lib.packages.ExternalPackage;
+import com.google.devtools.build.lib.packages.GlobCache;
+import com.google.devtools.build.lib.packages.MakeEnvironment;
+import com.google.devtools.build.lib.packages.Package;
+import com.google.devtools.build.lib.packages.Package.LegacyBuilder;
+import com.google.devtools.build.lib.packages.PackageFactory;
+import com.google.devtools.build.lib.packages.PackageFactory.LegacyGlobber;
+import com.google.devtools.build.lib.packages.PackageIdentifier;
+import com.google.devtools.build.lib.packages.RuleClassProvider;
+import com.google.devtools.build.lib.syntax.BuildFileAST;
+import com.google.devtools.build.lib.syntax.Label;
+import com.google.devtools.build.lib.syntax.ParserInputSource;
+import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.lib.testutil.TestRuleClassProvider;
+import com.google.devtools.build.lib.testutil.TestUtils;
+import com.google.devtools.build.lib.util.Pair;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
+
+import java.io.IOException;
+
+/**
+ * An apparatus that creates / maintains a {@link PackageFactory}.
+ */
+public class PackageFactoryApparatus {
+
+ private final EventCollectionApparatus events;
+ private final Scratch scratch;
+ private final CachingPackageLocator locator;
+
+ private final PackageFactory factory;
+
+ public PackageFactoryApparatus(EventCollectionApparatus events, Scratch scratch,
+ PackageFactory.EnvironmentExtension... environmentExtensions) {
+ this.events = events;
+ this.scratch = scratch;
+ RuleClassProvider ruleClassProvider = TestRuleClassProvider.getRuleClassProvider();
+
+ // This is used only in globbing and will cause us to always traverse
+ // subdirectories.
+ this.locator = createEmptyLocator();
+
+ factory = new PackageFactory(ruleClassProvider, null,
+ ImmutableList.copyOf(environmentExtensions));
+ }
+
+ /**
+ * Returns the package factory maintained by this apparatus.
+ */
+ public PackageFactory factory() {
+ return factory;
+ }
+
+ CachingPackageLocator getPackageLocator() {
+ return locator;
+ }
+
+ /**
+ * Parses and evaluates {@code buildFile} and returns the resulting {@link Package} instance.
+ */
+ public Package createPackage(String packageName, Path buildFile)
+ throws Exception {
+ return createPackage(packageName, buildFile, events.reporter());
+ }
+
+ /**
+ * Parses and evaluates {@code buildFile} with custom {@code reporter} and returns the resulting
+ * {@link Package} instance.
+ */
+ public Package createPackage(String packageName, Path buildFile,
+ Reporter reporter)
+ throws Exception {
+ try {
+ Package pkg = factory.createPackageForTesting(
+ PackageIdentifier.createInDefaultRepo(packageName), buildFile, locator, reporter);
+ return pkg;
+ } catch (InterruptedException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * Parses the {@code buildFile} into a {@link BuildFileAST}.
+ */
+ public BuildFileAST ast(Path buildFile) throws IOException {
+ ParserInputSource inputSource = ParserInputSource.create(buildFile);
+ return BuildFileAST.parseBuildFile(inputSource, events.reporter(), locator,
+ /*parsePython=*/false);
+ }
+
+ /**
+ * Parses the {@code lines} into a {@link BuildFileAST}.
+ */
+ public BuildFileAST ast(String fileName, String... lines)
+ throws IOException {
+ Path file = scratch.file(fileName, lines);
+ return ast(file);
+ }
+
+ /**
+ * Evaluates the {@code buildFileAST} into a {@link Package}.
+ */
+ public Pair<Package, GlobCache> evalAndReturnGlobCache(String packageName, Path buildFile,
+ BuildFileAST buildFileAST) throws InterruptedException {
+ PackageIdentifier packageId = PackageIdentifier.createInDefaultRepo(packageName);
+ GlobCache globCache = new GlobCache(
+ buildFile.getParentDirectory(), packageId, locator, null, TestUtils.getPool());
+ LegacyGlobber globber = new LegacyGlobber(globCache);
+ ExternalPackage externalPkg = (new ExternalPackage.Builder(
+ buildFile.getParentDirectory().getRelative("WORKSPACE"))).build();
+ LegacyBuilder resultBuilder = factory.evaluateBuildFile(
+ externalPkg, packageId, buildFileAST, buildFile,
+ globber, ImmutableList.<Event>of(), ConstantRuleVisibility.PUBLIC, false, false,
+ new MakeEnvironment.Builder(), ImmutableMap.<PathFragment, SkylarkEnvironment>of(),
+ ImmutableList.<Label>of());
+ Package result = resultBuilder.build();
+ Event.replayEventsOn(events.reporter(), result.getEvents());
+ return Pair.of(result, globCache);
+ }
+
+ public Package eval(String packageName, Path buildFile, BuildFileAST buildFileAST)
+ throws InterruptedException {
+ return evalAndReturnGlobCache(packageName, buildFile, buildFileAST).first;
+ }
+
+ /**
+ * Evaluates the {@code buildFileAST} into a {@link Package}.
+ */
+ public Package eval(String packageName, Path buildFile)
+ throws InterruptedException, IOException {
+ return eval(packageName, buildFile, ast(buildFile));
+ }
+
+ /**
+ * Creates a package locator that finds no packages.
+ */
+ public static CachingPackageLocator createEmptyLocator() {
+ return new CachingPackageLocator() {
+ @Override
+ public Path getBuildFileForPackage(String packageName) {
+ return null;
+ }
+ };
+ }
+}