blob: 0c9059dbd4e3e55a1392bda0b22db123a60db57f [file] [log] [blame]
// Copyright 2018 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.query2;
import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.packages.Attribute.attr;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;
import com.google.common.collect.Iterables;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.analysis.AnalysisProtos;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.config.TransitionFactories;
import com.google.devtools.build.lib.analysis.util.MockRule;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.NullEventHandler;
import com.google.devtools.build.lib.events.Reporter;
import com.google.devtools.build.lib.query2.ProtoOutputFormatterCallback.OutputType;
import com.google.devtools.build.lib.query2.engine.ConfiguredTargetQueryHelper;
import com.google.devtools.build.lib.query2.engine.ConfiguredTargetQueryTest;
import com.google.devtools.build.lib.query2.engine.QueryEnvironment.Setting;
import com.google.devtools.build.lib.query2.engine.QueryExpression;
import com.google.devtools.build.lib.query2.engine.QueryParser;
import com.google.devtools.build.lib.query2.output.AspectResolver.Mode;
import com.google.devtools.build.lib.query2.output.CqueryOptions;
import com.google.devtools.build.lib.query2.proto.proto2api.Build;
import com.google.devtools.build.lib.util.FileTypeSet;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.junit.Before;
import org.junit.Test;
/**
* Test for cquery's proto output format.
*
* <p>TODO(juliexxia): refactor all cquery output format tests to consolidate duplicate
* infrastructure.
*/
public class ProtoOutputFormatterCallbackTest extends ConfiguredTargetQueryTest {
private CqueryOptions options;
private Reporter reporter;
private final List<Event> events = new ArrayList<>();
@Before
public final void setUpCqueryOptions() {
this.options = new CqueryOptions();
options.aspectDeps = Mode.OFF;
options.protoIncludeConfigurations = true;
this.reporter = new Reporter(new EventBus(), events::add);
}
@Test
public void testSelectInAttribute() throws Exception {
MockRule depsRule =
() ->
MockRule.define(
"my_rule",
(builder, env) ->
builder
.add(attr("deps", LABEL_LIST).allowedFileTypes(FileTypeSet.ANY_FILE)));
helper.useRuleClassProvider(setRuleClassProviders(depsRule).build());
writeFile(
"test/BUILD",
"my_rule(name = 'my_rule',",
" deps = select({",
" ':garfield': ['lasagna.java', 'naps.java'],",
" '//conditions:default': ['mondays.java']",
" })",
")",
"config_setting(",
" name = 'garfield',",
" values = {'test_arg': 'cat'}",
")");
AnalysisProtos.ConfiguredTarget myRuleProto =
(Iterables.getOnlyElement(getOutput("//test:my_rule").getResultsList()));
List<Build.Attribute> attributes = myRuleProto.getTarget().getRule().getAttributeList();
for (Build.Attribute attribute : attributes) {
if (!attribute.getName().equals("deps")) {
continue;
}
assertThat(attribute.getStringListValueCount()).isEqualTo(1);
assertThat(attribute.getStringListValue(0)).isEqualTo("//test:mondays.java");
break;
}
getHelper().useConfiguration("--test_arg=cat");
myRuleProto = Iterables.getOnlyElement(getOutput("//test:my_rule").getResultsList());
attributes = myRuleProto.getTarget().getRule().getAttributeList();
for (Build.Attribute attribute : attributes) {
if (!attribute.getName().equals("deps")) {
continue;
}
assertThat(attribute.getStringListValueCount()).isEqualTo(2);
assertThat(attribute.getStringListValue(0)).isEqualTo("//test:lasagna.java");
assertThat(attribute.getStringListValue(1)).isEqualTo("//test:naps.java");
break;
}
}
@Test
public void testConfigurationHash() throws Exception {
TestArgPatchTransition attributePatchTransition = new TestArgPatchTransition("SET BY PATCH");
MockRule ruleWithPatch =
() ->
MockRule.define(
"my_rule",
(builder, env) ->
builder.add(
attr("deps", LABEL_LIST)
.allowedFileTypes(FileTypeSet.ANY_FILE)
.cfg(TransitionFactories.of(attributePatchTransition))));
helper.useRuleClassProvider(setRuleClassProviders(ruleWithPatch, getSimpleRule()).build());
writeFile(
"test/BUILD",
"my_rule(name = 'my_rule',",
" deps = [':patched'],",
")",
"simple_rule(name = 'dep')");
// Assert checksum from proto is proper checksum.
AnalysisProtos.ConfiguredTarget myRuleProto =
Iterables.getOnlyElement(getOutput("//test:my_rule").getResultsList());
ConfiguredTarget myRule = Iterables.getOnlyElement(eval("//test:my_rule"));
assertThat(myRuleProto.getConfiguration().getChecksum())
.isEqualTo(myRule.getConfigurationChecksum());
// Assert checksum for two configured targets in proto are not the same.
List<AnalysisProtos.ConfiguredTarget> protoDeps =
getOutput("deps(//test:my_rule)").getResultsList();
assertThat(protoDeps).hasSize(2);
Iterator<AnalysisProtos.ConfiguredTarget> protoDepsIterator = protoDeps.iterator();
assertThat(protoDepsIterator.next().getConfiguration().getChecksum())
.isNotEqualTo(protoDepsIterator.next().getConfiguration().getChecksum());
}
@Test
public void testAlias() throws Exception {
helper.useRuleClassProvider(setRuleClassProviders(getSimpleRule()).build());
writeFile(
"test/BUILD",
"simple_rule(name = 'my_rule')",
"alias(name = 'my_alias', actual = ':my_rule')");
AnalysisProtos.ConfiguredTarget alias =
Iterables.getOnlyElement(getOutput("//test:my_alias").getResultsList());
assertThat(alias.getTarget().getRule().getName()).isEqualTo("//test:my_alias");
assertThat(alias.getTarget().getRule().getRuleInputCount()).isEqualTo(1);
assertThat(alias.getTarget().getRule().getRuleInput(0)).isEqualTo("//test:my_rule");
}
/* See b/209787345 for context. */
@Test
public void testAlias_withSelect() throws Exception {
helper.useRuleClassProvider(setRuleClassProviders(getSimpleRule()).build());
writeFile(
"test/BUILD",
"alias(",
" name = 'my_alias_rule',",
" actual = select({",
" ':config1': ':target1',",
" '//conditions:default': ':target2',",
" }),",
")",
"config_setting(",
" name = 'config1',",
" values = {'test_arg': 'woof'},",
")",
"simple_rule(name = 'target1')",
"simple_rule(name = 'target2')");
getHelper().useConfiguration("--test_arg=woof");
helper.setQuerySettings(Setting.NO_IMPLICIT_DEPS);
List<AnalysisProtos.ConfiguredTarget> myAliasRuleProto =
getOutput("deps(//test:my_alias_rule)").getResultsList();
List<String> depNames = new ArrayList<>(myAliasRuleProto.size());
myAliasRuleProto.forEach(
configuredTarget -> depNames.add(configuredTarget.getTarget().getRule().getName()));
assertThat(depNames)
.containsExactly("//test:my_alias_rule", "//test:config1", "//test:target1");
}
private MockRule getSimpleRule() {
return () -> MockRule.define("simple_rule");
}
private AnalysisProtos.CqueryResult getOutput(String queryExpression) throws Exception {
QueryExpression expression = QueryParser.parse(queryExpression, getDefaultFunctions());
Set<String> targetPatternSet = new LinkedHashSet<>();
expression.collectTargetPatterns(targetPatternSet);
helper.setQuerySettings(Setting.NO_IMPLICIT_DEPS);
PostAnalysisQueryEnvironment<ConfiguredTarget> env =
((ConfiguredTargetQueryHelper) helper).getPostAnalysisQueryEnvironment(targetPatternSet);
ProtoOutputFormatterCallback callback =
new ProtoOutputFormatterCallback(
reporter,
options,
/*out=*/ null,
getHelper().getSkyframeExecutor(),
env.getAccessor(),
options.aspectDeps.createResolver(
getHelper().getPackageManager(), NullEventHandler.INSTANCE),
OutputType.BINARY);
env.evaluateQuery(expression, callback);
return callback.getProtoResult();
}
}