blob: 9cc798fc57a1a773e87407eed2b5e0a05d2c12c5 [file] [log] [blame]
// Copyright 2019 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.google.devtools.build.lib.analysis;
import static com.google.common.truth.Truth.assertThat;
import static com.google.devtools.build.lib.testutil.MoreAsserts.assertThrows;
import com.google.devtools.build.lib.analysis.util.AnalysisTestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Test for visibility of targets. */
@RunWith(JUnit4.class)
public class VisibilityTest extends AnalysisTestCase {
void setupArgsScenario() throws Exception {
scratch.file("tool/tool.sh", "#!/bin/sh", "echo Hello > $2", "cat $1 >> $2");
scratch.file("rule/BUILD");
scratch.file(
"rule/rule.bzl",
"def _impl(ctx):",
" output = ctx.actions.declare_file(ctx.label.name + '.out')",
" ctx.actions.run(",
" inputs = ctx.files._tool + ctx.files.data,",
" executable = ctx.files._tool[0].path,",
" arguments = [f.path for f in ctx.files.data] + [output.path],",
" outputs = [output],",
" )",
"",
"greet = rule(",
" implementation = _impl,",
" attrs = {",
" 'data' : attr.label(allow_files=True),",
" '_tool' : attr.label(cfg='host', allow_files=True,",
" default = Label('//tool:tool.sh')),",
" },",
" outputs = {'out' : '%{name}.out'},",
")");
scratch.file("data/data.txt", "World");
scratch.file(
"use/BUILD",
"load('//rule:rule.bzl', 'greet')",
"",
"greet(",
" name = 'world',",
" data = '//data:data.txt',",
")");
}
@Test
public void testToolVisibilityRuleCheckAtRule() throws Exception {
setupArgsScenario();
scratch.file("data/BUILD", "exports_files(['data.txt'], visibility=['//visibility:public'])");
scratch.file("tool/BUILD", "exports_files(['tool.sh'], visibility=['//rule:__pkg__'])");
useConfiguration("--incompatible_visibility_private_attributes_at_definition");
update("//use:world");
assertThat(hasErrors(getConfiguredTarget("//use:world"))).isFalse();
}
@Test
public void testToolVisibilityRuleCheckAtUse() throws Exception {
setupArgsScenario();
scratch.file("data/BUILD", "exports_files(['data.txt'], visibility=['//visibility:public'])");
scratch.file("tool/BUILD", "exports_files(['tool.sh'], visibility=['//rule:__pkg__'])");
useConfiguration("--noincompatible_visibility_private_attributes_at_definition");
reporter.removeHandler(failFastHandler);
assertThrows(ViewCreationFailedException.class, () -> update("//use:world"));
}
@Test
public void testToolVisibilityUseCheckAtUse() throws Exception {
setupArgsScenario();
scratch.file("data/BUILD", "exports_files(['data.txt'], visibility=['//visibility:public'])");
scratch.file("tool/BUILD", "exports_files(['tool.sh'], visibility=['//use:__pkg__'])");
useConfiguration("--noincompatible_visibility_private_attributes_at_definition");
update("//use:world");
assertThat(hasErrors(getConfiguredTarget("//use:world"))).isFalse();
}
@Test
public void testToolVisibilityUseCheckAtRule() throws Exception {
setupArgsScenario();
scratch.file("data/BUILD", "exports_files(['data.txt'], visibility=['//visibility:public'])");
scratch.file("tool/BUILD", "exports_files(['tool.sh'], visibility=['//use:__pkg__'])");
useConfiguration("--incompatible_visibility_private_attributes_at_definition");
reporter.removeHandler(failFastHandler);
assertThrows(ViewCreationFailedException.class, () -> update("//use:world"));
}
@Test
public void testToolVisibilityPrivateCheckAtUse() throws Exception {
setupArgsScenario();
scratch.file("data/BUILD", "exports_files(['data.txt'], visibility=['//visibility:public'])");
scratch.file("tool/BUILD", "exports_files(['tool.sh'], visibility=['//visibility:private'])");
useConfiguration("--noincompatible_visibility_private_attributes_at_definition");
reporter.removeHandler(failFastHandler);
assertThrows(ViewCreationFailedException.class, () -> update("//use:world"));
}
@Test
public void testToolVisibilityPrivateCheckAtRule() throws Exception {
setupArgsScenario();
scratch.file("data/BUILD", "exports_files(['data.txt'], visibility=['//visibility:public'])");
scratch.file("tool/BUILD", "exports_files(['tool.sh'], visibility=['//visibility:private'])");
useConfiguration("--incompatible_visibility_private_attributes_at_definition");
reporter.removeHandler(failFastHandler);
assertThrows(ViewCreationFailedException.class, () -> update("//use:world"));
}
@Test
public void testDataVisibilityUseCheckPrivateAtUse() throws Exception {
setupArgsScenario();
scratch.file("data/BUILD", "exports_files(['data.txt'], visibility=['//use:__pkg__'])");
scratch.file("tool/BUILD", "exports_files(['tool.sh'], visibility=['//visibility:public'])");
useConfiguration("--noincompatible_visibility_private_attributes_at_definition");
update("//use:world");
assertThat(hasErrors(getConfiguredTarget("//use:world"))).isFalse();
}
@Test
public void testDataVisibilityUseCheckPrivateAtRule() throws Exception {
setupArgsScenario();
scratch.file("data/BUILD", "exports_files(['data.txt'], visibility=['//use:__pkg__'])");
scratch.file("tool/BUILD", "exports_files(['tool.sh'], visibility=['//visibility:public'])");
useConfiguration("--incompatible_visibility_private_attributes_at_definition");
update("//use:world");
assertThat(hasErrors(getConfiguredTarget("//use:world"))).isFalse();
}
@Test
public void testDataVisibilityPrivateCheckPrivateAtRule() throws Exception {
setupArgsScenario();
scratch.file("data/BUILD", "exports_files(['data.txt'], visibility=['//visibility:private'])");
scratch.file("tool/BUILD", "exports_files(['tool.sh'], visibility=['//visibility:public'])");
useConfiguration("--incompatible_visibility_private_attributes_at_definition");
reporter.removeHandler(failFastHandler);
assertThrows(ViewCreationFailedException.class, () -> update("//use:world"));
}
@Test
public void testDataVisibilityPrivateCheckPrivateAtUse() throws Exception {
setupArgsScenario();
scratch.file("data/BUILD", "exports_files(['data.txt'], visibility=['//visibility:private'])");
scratch.file("tool/BUILD", "exports_files(['tool.sh'], visibility=['//visibility:public'])");
useConfiguration("--noincompatible_visibility_private_attributes_at_definition");
reporter.removeHandler(failFastHandler);
assertThrows(ViewCreationFailedException.class, () -> update("//use:world"));
}
void setupFilesScenario(String wantRead) throws Exception {
scratch.file("src/source.txt", "source");
scratch.file("src/BUILD", "exports_files(['source.txt'], visibility=['//pkg:__pkg__'])");
scratch.file("pkg/foo.txt", "foo");
scratch.file("pkg/bar.txt", "bar");
scratch.file("pkg/groupfile.txt", "groupfile");
scratch.file("pkg/unused.txt", "unused");
scratch.file("pkg/exported.txt", "exported");
scratch.file(
"pkg/BUILD",
"package(default_visibility=['//visibility:public'])",
"exports_files(['exported.txt'])",
"",
"genrule(",
" name = 'foobar',",
" outs = ['foobar.txt'],",
" srcs = ['foo.txt', 'bar.txt'],",
" cmd = 'cat $(SRCS) > $@',",
")",
"",
"filegroup(",
" name = 'remotegroup',",
" srcs = ['//src:source.txt'],",
")",
"",
"filegroup(",
" name = 'localgroup',",
" srcs = [':groupfile.txt'],",
")");
scratch.file(
"otherpkg/BUILD",
"genrule(",
" name = 'it',",
" srcs = ['//pkg:" + wantRead + "'],",
" outs = ['it.xt'],",
" cmd = 'cp $< $@',",
")");
}
@Test
public void testTargetImplicitExport() throws Exception {
setupFilesScenario("foobar");
useConfiguration("--noincompatible_no_implicit_file_export");
update("//otherpkg:it");
assertThat(hasErrors(getConfiguredTarget("//otherpkg:it"))).isFalse();
}
@Test
public void testTargetNoImplicitExport() throws Exception {
setupFilesScenario("foobar");
useConfiguration("--incompatible_no_implicit_file_export");
update("//otherpkg:it");
assertThat(hasErrors(getConfiguredTarget("//otherpkg:it"))).isFalse();
}
@Test
public void testLocalFilegroupImplicitExport() throws Exception {
setupFilesScenario("localgroup");
useConfiguration("--noincompatible_no_implicit_file_export");
update("//otherpkg:it");
assertThat(hasErrors(getConfiguredTarget("//otherpkg:it"))).isFalse();
}
@Test
public void testLocalFilegroupNoImplicitExport() throws Exception {
setupFilesScenario("localgroup");
useConfiguration("--incompatible_no_implicit_file_export");
update("//otherpkg:it");
assertThat(hasErrors(getConfiguredTarget("//otherpkg:it"))).isFalse();
}
@Test
public void testRemoteFilegroupImplicitExport() throws Exception {
setupFilesScenario("remotegroup");
useConfiguration("--noincompatible_no_implicit_file_export");
update("//otherpkg:it");
assertThat(hasErrors(getConfiguredTarget("//otherpkg:it"))).isFalse();
}
@Test
public void testRemoteFilegroupNoImplicitExport() throws Exception {
setupFilesScenario("remotegroup");
useConfiguration("--incompatible_no_implicit_file_export");
update("//otherpkg:it");
assertThat(hasErrors(getConfiguredTarget("//otherpkg:it"))).isFalse();
}
@Test
public void testExportedImplicitExport() throws Exception {
setupFilesScenario("exported.txt");
useConfiguration("--noincompatible_no_implicit_file_export");
update("//otherpkg:it");
assertThat(hasErrors(getConfiguredTarget("//otherpkg:it"))).isFalse();
}
@Test
public void testExportedNoImplicitExport() throws Exception {
setupFilesScenario("exported.txt");
useConfiguration("--incompatible_no_implicit_file_export");
update("//otherpkg:it");
assertThat(hasErrors(getConfiguredTarget("//otherpkg:it"))).isFalse();
}
@Test
public void testUnusedImplicitExport() throws Exception {
setupFilesScenario("unused.txt");
useConfiguration("--noincompatible_no_implicit_file_export");
reporter.removeHandler(failFastHandler);
assertThrows(ViewCreationFailedException.class, () -> update("//otherpkg:it"));
}
@Test
public void testUnusedNoImplicitExport() throws Exception {
setupFilesScenario("unused.txt");
useConfiguration("--incompatible_no_implicit_file_export");
reporter.removeHandler(failFastHandler);
assertThrows(ViewCreationFailedException.class, () -> update("//otherpkg:it"));
}
@Test
public void testSourcefileImplicitExport() throws Exception {
setupFilesScenario("foo.txt");
useConfiguration("--noincompatible_no_implicit_file_export");
update("//otherpkg:it");
assertThat(hasErrors(getConfiguredTarget("//otherpkg:it"))).isFalse();
}
@Test
public void testSourcefileNoImplicitExport() throws Exception {
setupFilesScenario("foo.txt");
useConfiguration("--incompatible_no_implicit_file_export");
reporter.removeHandler(failFastHandler);
assertThrows(ViewCreationFailedException.class, () -> update("//otherpkg:it"));
}
}