| /* |
| * 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.BuildTargetFactory; |
| 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.base.Functions; |
| 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.util.Comparator; |
| |
| public class AbstractBuildRuleTest { |
| |
| private static final BuildTarget orcaTarget = BuildTargetFactory.newInstance( |
| "//src/com/facebook/orca", "orca"); |
| private static final BuildTarget publicTarget = BuildTargetFactory.newInstance( |
| "//src/com/facebook/for", "everyone"); |
| private static final BuildTarget nonPublicTarget1 = BuildTargetFactory.newInstance( |
| "//src/com/facebook/something1", "nonPublic"); |
| private static final BuildTarget nonPublicTarget2 = BuildTargetFactory.newInstance( |
| "//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 = BuildTargetFactory.newInstance("//lib", "lib"); |
| BuildTarget targetInSpecifiedDirectory = BuildTargetFactory.newInstance( |
| "//src/com/facebook", "test"); |
| BuildTarget targetUnderSpecifiedDirectory = BuildTargetFactory.newInstance( |
| "//src/com/facebook/buck", "test"); |
| BuildTarget targetInOtherDirectory = BuildTargetFactory.newInstance( |
| "//src/com/instagram", "test"); |
| BuildTarget targetInParentDirectory = BuildTargetFactory.newInstance( |
| "//", "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 BuildRuleParams( |
| buildTarget, |
| sortedDeps, |
| visibilityPatterns, |
| /* pathRelativizer */ Functions.<String>identity()); |
| return new AbstractBuildRule(buildRuleParams) { |
| @Override |
| public BuildRuleType getType() { |
| 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<InputRule> getInputs() { |
| return ImmutableList.of(); |
| } |
| |
| @Override |
| public RuleKey.Builder appendToRuleKey(RuleKey.Builder builder) { |
| throw new IllegalStateException("This method should not be called"); |
| } |
| }; |
| } |
| } |