blob: 0d363b9cc31f7f9e43915770c74ff49a053b6195 [file] [log] [blame]
// Copyright 2015 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.analysis.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.cmdline.Label;
import com.google.devtools.build.lib.packages.AggregatingAttributeMapper;
import com.google.devtools.build.lib.packages.Attribute;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.syntax.Type;
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", BuildType.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'],",
" '" + BuildType.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", BuildType.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", BuildType.LABEL_LIST));
}
/**
* Given a large number of selects, we expect better than the naive
* exponential performance from evaluating select1 x select2 x select3 x ...
*/
public void testGetPossibleValuesWithManySelects() throws Exception {
String pattern = " + select({'//conditions:a1': '%c', '//conditions:a2': '%s'})";
StringBuilder ruleDef = new StringBuilder();
ruleDef.append("genrule(name = 'gen', srcs = [], outs = ['gen.out'], cmd = ''");
for (char c : "abcdefghijklmnopqrstuvwxyz".toCharArray()) {
ruleDef.append(String.format(pattern, c, Character.toUpperCase(c)));
}
ruleDef.append(")");
Rule rule = createRule("a", "gen", ruleDef.toString());
assertSameContents(
ImmutableList.of("abcdefghijklmnopqrstuvwxyz", "ABCDEFGHIJKLMNOPQRSTUVWXYZ"),
// Naive evaluation would visit 2^26 cases and either overflow memory or timeout the test.
AggregatingAttributeMapper.of(rule).visitAttribute("cmd", Type.STRING));
}
/**
* 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'],",
" '" + BuildType.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'],",
" '" + BuildType.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));
}
}