blob: 361a929c27d8c2c4e167f30f591c926e7092c858 [file] [log] [blame]
/*
* Copyright 2012-present Facebook, Inc.
*
* 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.facebook.buck.rules;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.model.SingletonBuildTargetPattern;
import com.facebook.buck.model.SubdirectoryBuildTargetPattern;
import com.facebook.buck.rules.BuildRuleSuccess.Type;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.util.concurrent.ListenableFuture;
import org.junit.Test;
import java.nio.file.Path;
import java.util.Comparator;
import javax.annotation.Nullable;
public class AbstractBuildRuleTest {
private static final BuildTarget orcaTarget = new BuildTarget("//src/com/facebook/orca", "orca");
private static final BuildTarget publicTarget = new BuildTarget("//src/com/facebook/for", "everyone");
private static final BuildTarget nonPublicTarget1 = new BuildTarget("//src/com/facebook/something1", "nonPublic");
private static final BuildTarget nonPublicTarget2 = new BuildTarget("//src/com/facebook/something2", "nonPublic");
private static final ImmutableSet<BuildRule> noDeps = ImmutableSet.of();
private static final ImmutableSet<BuildTargetPattern> noVisibilityPatterns = ImmutableSet.of();
@Test
public void testVisibilityPublic() {
BuildRule publicBuildRule = createRule(publicTarget, noDeps,
ImmutableSet.of(BuildTargetPattern.MATCH_ALL));
AbstractBuildRule orcaRule = createRule(orcaTarget, ImmutableSet.of(publicBuildRule),
noVisibilityPatterns);
assertTrue(publicBuildRule.isVisibleTo(orcaTarget));
assertFalse(orcaRule.isVisibleTo(publicTarget));
}
@Test
public void testVisibilityNonPublic() {
BuildRule nonPublicBuildRule1 = createRule(nonPublicTarget1, noDeps,
ImmutableSet.<BuildTargetPattern>of(
new SingletonBuildTargetPattern(orcaTarget.getFullyQualifiedName())));
BuildRule nonPublicBuildRule2 = createRule(nonPublicTarget2, noDeps,
ImmutableSet.<BuildTargetPattern>of(new SingletonBuildTargetPattern(orcaTarget.getFullyQualifiedName())));
AbstractBuildRule orcaRule = createRule(orcaTarget,
ImmutableSet.of(nonPublicBuildRule1, nonPublicBuildRule2),
noVisibilityPatterns);
assertTrue(shouldBeVisibleMessage(nonPublicBuildRule1, orcaTarget),
nonPublicBuildRule1.isVisibleTo(orcaTarget));
assertTrue(shouldBeVisibleMessage(nonPublicBuildRule2, orcaTarget),
nonPublicBuildRule2.isVisibleTo(orcaTarget));
assertFalse(orcaRule.isVisibleTo(nonPublicTarget1));
assertFalse(orcaRule.isVisibleTo(nonPublicTarget2));
BuildRule publicBuildRule = createRule(publicTarget,
noDeps,
ImmutableSet.of(BuildTargetPattern.MATCH_ALL));
assertTrue(publicBuildRule.isVisibleTo(nonPublicTarget1));
assertFalse(nonPublicBuildRule1.isVisibleTo(publicTarget));
}
@Test
public void testVisibilityNonPublicFailure() {
BuildRule nonPublicBuildRule1 = createRule(nonPublicTarget1,
noDeps,
ImmutableSet.<BuildTargetPattern>of(
new SingletonBuildTargetPattern(orcaTarget.getFullyQualifiedName())));
try {
createRule(publicTarget,
ImmutableSet.of(nonPublicBuildRule1),
ImmutableSet.of(BuildTargetPattern.MATCH_ALL));
fail("createRule() should throw an exception");
} catch (RuntimeException e) {
assertEquals(
String.format("%s depends on %s, which is not visible",
publicTarget,
nonPublicBuildRule1),
e.getMessage());
}
}
@Test
public void testVisibilityMix() {
BuildRule nonPublicBuildRule1 = createRule(nonPublicTarget1,
noDeps,
ImmutableSet.<BuildTargetPattern>of(new SingletonBuildTargetPattern(orcaTarget.getFullyQualifiedName())));
BuildRule nonPublicBuildRule2 = createRule(nonPublicTarget2,
noDeps,
ImmutableSet.<BuildTargetPattern>of(new SingletonBuildTargetPattern(orcaTarget.getFullyQualifiedName())));
BuildRule publicBuildRule = createRule(publicTarget,
noDeps,
ImmutableSet.of(BuildTargetPattern.MATCH_ALL));
AbstractBuildRule orcaRule = createRule(orcaTarget,
ImmutableSet.of(publicBuildRule, nonPublicBuildRule1, nonPublicBuildRule2),
noVisibilityPatterns);
assertTrue(shouldBeVisibleMessage(nonPublicBuildRule1, orcaTarget),
nonPublicBuildRule1.isVisibleTo(orcaTarget));
assertTrue(shouldBeVisibleMessage(nonPublicBuildRule2, orcaTarget),
nonPublicBuildRule2.isVisibleTo(orcaTarget));
assertTrue(publicBuildRule.isVisibleTo(orcaTarget));
assertFalse(orcaRule.isVisibleTo(nonPublicTarget1));
assertFalse(orcaRule.isVisibleTo(nonPublicTarget2));
assertFalse(orcaRule.isVisibleTo(publicTarget));
}
@Test
public void testVisibilityMixFailure() {
BuildRule nonPublicBuildRule1 = createRule(nonPublicTarget1,
noDeps,
ImmutableSet.<BuildTargetPattern>of(
new SingletonBuildTargetPattern(orcaTarget.getFullyQualifiedName())));
BuildRule nonPublicBuildRule2 = createRule(nonPublicTarget2,
noDeps,
ImmutableSet.<BuildTargetPattern>of(
new SingletonBuildTargetPattern("//some/other:target")));
BuildRule publicBuildRule = createRule(publicTarget,
noDeps,
ImmutableSet.of(BuildTargetPattern.MATCH_ALL));
try {
createRule(orcaTarget,
ImmutableSet.of(publicBuildRule, nonPublicBuildRule1, nonPublicBuildRule2),
noVisibilityPatterns);
fail("createRule() should throw an exception");
} catch (RuntimeException e) {
assertEquals(
String.format("%s depends on %s, which is not visible", orcaTarget, nonPublicBuildRule2),
e.getMessage());
}
}
@Test
public void testVisibilityForDirectory() {
BuildTarget libTarget = new BuildTarget("//lib", "lib");
BuildTarget targetInSpecifiedDirectory = new BuildTarget("//src/com/facebook", "test");
BuildTarget targetUnderSpecifiedDirectory = new BuildTarget("//src/com/facebook/buck", "test");
BuildTarget targetInOtherDirectory = new BuildTarget("//src/com/instagram", "test");
BuildTarget targetInParentDirectory = new BuildTarget("//", "test");
// Build rule that visible to targets in or under directory src/come/facebook
BuildRule directoryBuildRule = createRule(libTarget,
noDeps,
ImmutableSet.<BuildTargetPattern>of(
new SubdirectoryBuildTargetPattern("src/com/facebook/")));
assertTrue(directoryBuildRule.isVisibleTo(targetInSpecifiedDirectory));
assertTrue(directoryBuildRule.isVisibleTo(targetUnderSpecifiedDirectory));
assertFalse(directoryBuildRule.isVisibleTo(targetInOtherDirectory));
assertFalse(directoryBuildRule.isVisibleTo(targetInParentDirectory));
// Build rule that visible to all targets, equals to PUBLIC.
BuildRule pubicBuildRule = createRule(libTarget,
noDeps,
ImmutableSet.<BuildTargetPattern>of(new SubdirectoryBuildTargetPattern("")));
assertTrue(pubicBuildRule.isVisibleTo(targetInSpecifiedDirectory));
assertTrue(pubicBuildRule.isVisibleTo(targetUnderSpecifiedDirectory));
assertTrue(pubicBuildRule.isVisibleTo(targetInOtherDirectory));
assertTrue(pubicBuildRule.isVisibleTo(targetInParentDirectory));
}
private String shouldBeVisibleMessage(BuildRule rule, BuildTarget target) {
return String.format(
"%1$s should be visible to %2$s because the visibility list of %1$s contains %2$s",
rule,
target);
}
private static AbstractBuildRule createRule(BuildTarget buildTarget,
ImmutableSet<BuildRule> deps,
ImmutableSet<BuildTargetPattern> visibilityPatterns) {
Comparator<BuildRule> comparator = RetainOrderComparator.createComparator(deps);
ImmutableSortedSet<BuildRule> sortedDeps = ImmutableSortedSet.copyOf(comparator, deps);
BuildRuleParams buildRuleParams = new FakeBuildRuleParams(
buildTarget,
sortedDeps,
visibilityPatterns);
return new AbstractBuildRule(buildRuleParams) {
@Override
public BuildRuleType getType() {
throw new IllegalStateException("This method should not be called");
}
@Nullable
@Override
public Buildable getBuildable() {
throw new IllegalStateException("This method should not be called");
}
@Override
public ListenableFuture<BuildRuleSuccess> build(BuildContext context) {
throw new IllegalStateException("This method should not be called");
}
@Override
public Type getBuildResultType() {
throw new IllegalStateException("This method should not be called");
}
@Override
public final Iterable<Path> getInputs() {
return ImmutableList.of();
}
@Override
public RuleKey.Builder appendToRuleKey(RuleKey.Builder builder) {
throw new IllegalStateException("This method should not be called");
}
};
}
}