/*
* 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.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import com.facebook.buck.io.ArchiveMemberPath;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.jvm.java.JavaLibraryBuilder;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.rules.keys.DefaultRuleKeyFactory;
import com.facebook.buck.rules.keys.RuleKeyBuilder;
import com.facebook.buck.rules.keys.RuleKeyFactory;
import com.facebook.buck.rules.keys.RuleKeyResult;
import com.facebook.buck.rules.keys.UncachedRuleKeyBuilder;
import com.facebook.buck.testutil.FakeFileHashCache;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.util.HumanReadableException;
import com.facebook.buck.util.cache.DefaultFileHashCache;
import com.facebook.buck.util.cache.FileHashCache;
import com.facebook.buck.util.cache.NullFileHashCache;
import com.facebook.buck.util.cache.StackedFileHashCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.hash.HashCode;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.Test;
public class RuleKeyTest {
@Test
public void testRuleKeyFromHashString() {
RuleKey ruleKey = new RuleKey("19d2558a6bd3a34fb3f95412de9da27ed32fe208");
assertEquals("19d2558a6bd3a34fb3f95412de9da27ed32fe208", ruleKey.toString());
}
@Test(expected = HumanReadableException.class)
public void shouldNotAllowPathsInRuleKeysWhenSetReflectively() {
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKeyBuilder<HashCode> builder = createBuilder(resolver, ruleFinder);
builder.setReflectively("path", Paths.get("some/path"));
}
/** Ensure that build rules with the same inputs but different deps have unique RuleKeys. */
@Test
public void testRuleKeyDependsOnDeps() throws Exception {
FakeProjectFilesystem filesystem = new FakeProjectFilesystem();
FileHashCache hashCache =
new StackedFileHashCache(
ImmutableList.of(DefaultFileHashCache.createDefaultFileHashCache(filesystem)));
BuildRuleResolver ruleResolver1 =
new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
BuildRuleResolver ruleResolver2 =
new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
SourcePathRuleFinder ruleFinder1 = new SourcePathRuleFinder(ruleResolver1);
DefaultRuleKeyFactory ruleKeyFactory =
new DefaultRuleKeyFactory(0, hashCache, new SourcePathResolver(ruleFinder1), ruleFinder1);
SourcePathRuleFinder ruleFinder2 = new SourcePathRuleFinder(ruleResolver2);
DefaultRuleKeyFactory ruleKeyFactory2 =
new DefaultRuleKeyFactory(0, hashCache, new SourcePathResolver(ruleFinder2), ruleFinder2);
// Create a dependent build rule, //src/com/facebook/buck/cli:common.
JavaLibraryBuilder builder =
JavaLibraryBuilder.createBuilder(
BuildTargetFactory.newInstance("//src/com/facebook/buck/cli:common"));
BuildRule commonJavaLibrary = builder.build(ruleResolver1);
builder.build(ruleResolver2);
// Create a java_library() rule with no deps.
Path mainSrc = Paths.get("src/com/facebook/buck/cli/Main.java");
filesystem.mkdirs(mainSrc.getParent());
filesystem.writeContentsToPath("hello", mainSrc);
JavaLibraryBuilder javaLibraryBuilder =
JavaLibraryBuilder.createBuilder(
BuildTargetFactory.newInstance("//src/com/facebook/buck/cli:cli"))
.addSrc(mainSrc);
BuildRule libraryNoCommon = javaLibraryBuilder.build(ruleResolver1, filesystem);
// Create the same java_library() rule, but with a dep on //src/com/facebook/buck/cli:common.
javaLibraryBuilder.addDep(commonJavaLibrary.getBuildTarget());
BuildRule libraryWithCommon = javaLibraryBuilder.build(ruleResolver2, filesystem);
// Assert that the RuleKeys are distinct.
RuleKey r1 = ruleKeyFactory.build(libraryNoCommon);
RuleKey r2 = ruleKeyFactory2.build(libraryWithCommon);
assertThat(
"Rule keys should be distinct because the deps of the rules are different.",
r1,
not(equalTo(r2)));
}
@Test
public void ensureSimpleValuesCorrectRuleKeyChangesMade() {
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey reflective =
createBuilder(resolver, ruleFinder)
.setReflectively("long", 42L)
.setReflectively("boolean", true)
.setReflectively("path", new FakeSourcePath("location/of/the/rebel/plans"))
.build(RuleKey::new);
RuleKey manual =
createBuilder(resolver, ruleFinder)
.setReflectively("long", 42L)
.setReflectively("boolean", true)
.setReflectively("path", new FakeSourcePath("location/of/the/rebel/plans"))
.build(RuleKey::new);
assertEquals(manual, reflective);
}
@Test
public void ensureTwoListsOfSameRuleKeyAppendablesHaveSameRuleKey() {
ImmutableList<TestRuleKeyAppendable> ruleKeyAppendableList =
ImmutableList.of(new TestRuleKeyAppendable("foo"), new TestRuleKeyAppendable("bar"));
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey ruleKeyPairA =
createBuilder(resolver, ruleFinder)
.setReflectively("ruleKeyAppendableList", ruleKeyAppendableList)
.build(RuleKey::new);
RuleKey ruleKeyPairB =
createBuilder(resolver, ruleFinder)
.setReflectively("ruleKeyAppendableList", ruleKeyAppendableList)
.build(RuleKey::new);
assertEquals(ruleKeyPairA, ruleKeyPairB);
}
@Test
public void ensureTwoListsOfDifferentRuleKeyAppendablesHaveDifferentRuleKeys() {
ImmutableList<TestRuleKeyAppendable> ruleKeyAppendableListA =
ImmutableList.of(new TestRuleKeyAppendable("foo"), new TestRuleKeyAppendable("bar"));
ImmutableList<TestRuleKeyAppendable> ruleKeyAppendableListB =
ImmutableList.of(new TestRuleKeyAppendable("bar"), new TestRuleKeyAppendable("foo"));
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey ruleKeyPairA =
createBuilder(resolver, ruleFinder)
.setReflectively("ruleKeyAppendableList", ruleKeyAppendableListA)
.build(RuleKey::new);
RuleKey ruleKeyPairB =
createBuilder(resolver, ruleFinder)
.setReflectively("ruleKeyAppendableList", ruleKeyAppendableListB)
.build(RuleKey::new);
assertNotEquals(ruleKeyPairA, ruleKeyPairB);
}
@Test
public void ensureTwoMapsOfSameRuleKeyAppendablesHaveSameRuleKey() {
ImmutableMap<String, TestRuleKeyAppendable> ruleKeyAppendableMap =
ImmutableMap.of(
"foo", new TestRuleKeyAppendable("foo"),
"bar", new TestRuleKeyAppendable("bar"));
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey ruleKeyPairA =
createBuilder(resolver, ruleFinder)
.setReflectively("ruleKeyAppendableMap", ruleKeyAppendableMap)
.build(RuleKey::new);
RuleKey ruleKeyPairB =
createBuilder(resolver, ruleFinder)
.setReflectively("ruleKeyAppendableMap", ruleKeyAppendableMap)
.build(RuleKey::new);
assertEquals(ruleKeyPairA, ruleKeyPairB);
}
@Test
public void ensureTwoMapsOfDifferentRuleKeyAppendablesHaveDifferentRuleKeys() {
ImmutableMap<String, TestRuleKeyAppendable> ruleKeyAppendableMapA =
ImmutableMap.of(
"foo", new TestRuleKeyAppendable("foo"),
"bar", new TestRuleKeyAppendable("bar"));
ImmutableMap<String, TestRuleKeyAppendable> ruleKeyAppendableMapB =
ImmutableMap.of(
"bar", new TestRuleKeyAppendable("bar"),
"foo", new TestRuleKeyAppendable("foo"));
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey ruleKeyPairA =
createBuilder(resolver, ruleFinder)
.setReflectively("ruleKeyAppendableMap", ruleKeyAppendableMapA)
.build(RuleKey::new);
RuleKey ruleKeyPairB =
createBuilder(resolver, ruleFinder)
.setReflectively("ruleKeyAppendableMap", ruleKeyAppendableMapB)
.build(RuleKey::new);
assertNotEquals(ruleKeyPairA, ruleKeyPairB);
}
@Test
public void ensureListsAreHandledProperly() {
ImmutableList<SourceRoot> sourceroots = ImmutableList.of(new SourceRoot("cake"));
ImmutableList<String> strings = ImmutableList.of("one", "two");
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey reflective =
createBuilder(resolver, ruleFinder)
.setReflectively("sourceroot", sourceroots)
.setReflectively("strings", strings)
.build(RuleKey::new);
RuleKey manual =
createBuilder(resolver, ruleFinder)
.setReflectively("sourceroot", sourceroots)
.setReflectively("strings", strings)
.build(RuleKey::new);
assertEquals(manual, reflective);
}
@Test
public void differentSeedsMakeDifferentKeys() {
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
BuildTarget buildTarget = BuildTargetFactory.newInstance("//some:example");
BuildRule buildRule = new FakeBuildRule(buildTarget, resolver);
RuleKey empty1 =
new DefaultRuleKeyFactory(0, new NullFileHashCache(), resolver, ruleFinder)
.build(buildRule);
RuleKey empty2 =
new DefaultRuleKeyFactory(0, new NullFileHashCache(), resolver, ruleFinder)
.build(buildRule);
RuleKey empty3 =
new DefaultRuleKeyFactory(1, new NullFileHashCache(), resolver, ruleFinder)
.build(buildRule);
assertThat(empty1, is(equalTo(empty2)));
assertThat(empty1, is(not(equalTo(empty3))));
}
@Test
public void testRuleKeyEqualsAndHashCodeMethods() {
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey keyPair1 =
createBuilder(resolver, ruleFinder).setReflectively("something", "foo").build(RuleKey::new);
RuleKey keyPair2 =
createBuilder(resolver, ruleFinder).setReflectively("something", "foo").build(RuleKey::new);
RuleKey keyPair3 =
createBuilder(resolver, ruleFinder).setReflectively("something", "bar").build(RuleKey::new);
assertEquals(keyPair1, keyPair2);
assertEquals(keyPair1.hashCode(), keyPair2.hashCode());
assertNotEquals(keyPair1, keyPair3);
assertNotEquals(keyPair1.hashCode(), keyPair3.hashCode());
assertNotEquals(keyPair2, keyPair3);
assertNotEquals(keyPair2.hashCode(), keyPair3.hashCode());
}
@Test
public void setInputPathSourcePath() {
ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
// Changing the name of a named source path should change the hash...
assertNotEquals(
buildResult(
createBuilder(resolver, ruleFinder)
.setReflectively(
"key", new PathSourcePath(projectFilesystem, Paths.get("something")))),
buildResult(
createBuilder(resolver, ruleFinder)
.setReflectively(
"key", new PathSourcePath(projectFilesystem, Paths.get("something", "else")))));
// ... as should changing the key
assertNotEquals(
buildResult(
createBuilder(resolver, ruleFinder)
.setReflectively(
"key", new PathSourcePath(projectFilesystem, Paths.get("something")))),
buildResult(
createBuilder(resolver, ruleFinder)
.setReflectively(
"different-key",
new PathSourcePath(projectFilesystem, Paths.get("something")))));
}
@Test
public void setNonHashingSourcePathsWithDifferentRelativePaths() {
ProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
PathSourcePath sourcePathOne = new PathSourcePath(projectFilesystem, Paths.get("something"));
PathSourcePath sourcePathTwo = new PathSourcePath(projectFilesystem, Paths.get("something2"));
// Changing the relative path should change the rule key
SourcePathRuleFinder ruleFinder1 =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathRuleFinder ruleFinder2 =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
assertNotEquals(
buildResult(
createBuilder(new SourcePathResolver(ruleFinder1), ruleFinder1)
.setReflectively("key", new NonHashableSourcePathContainer(sourcePathOne))),
buildResult(
createBuilder(new SourcePathResolver(ruleFinder2), ruleFinder2)
.setReflectively("key", new NonHashableSourcePathContainer(sourcePathTwo))));
}
@Test
public void setInputBuildTargetSourcePath() {
BuildRuleResolver resolver =
new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver);
SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder);
FakeBuildRule fake1 = new FakeBuildRule("//:fake1", pathResolver);
FakeBuildRule fake2 = new FakeBuildRule("//:fake2", pathResolver);
resolver.addToIndex(fake1);
resolver.addToIndex(fake2);
// Verify that two BuildTargetSourcePaths with the same rule and path are equal.
assertEquals(
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key",
new ExplicitBuildTargetSourcePath(
fake1.getBuildTarget(), Paths.get("location")))),
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key",
new ExplicitBuildTargetSourcePath(
fake1.getBuildTarget(), Paths.get("location")))));
// Verify that just changing the path of the build rule changes the rule key.
assertNotEquals(
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key",
new ExplicitBuildTargetSourcePath(
fake1.getBuildTarget(), Paths.get("location")))),
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key",
new ExplicitBuildTargetSourcePath(
fake1.getBuildTarget(), Paths.get("different")))));
// Verify that just changing the build rule rule key changes the calculated rule key.
assertNotEquals(
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key",
new ExplicitBuildTargetSourcePath(
fake1.getBuildTarget(), Paths.get("location")))),
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key",
new ExplicitBuildTargetSourcePath(
fake2.getBuildTarget(), Paths.get("location")))));
// Verify that just changing the key changes the calculated rule key.
assertNotEquals(
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key",
new ExplicitBuildTargetSourcePath(
fake1.getBuildTarget(), Paths.get("location")))),
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"different-key",
new ExplicitBuildTargetSourcePath(
fake1.getBuildTarget(), Paths.get("location")))));
}
@Test
public void setInputArchiveMemberSourcePath() {
BuildRuleResolver resolver =
new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer());
SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver);
SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder);
final FakeBuildRule fakeBuildRule = new FakeBuildRule("//:fake", pathResolver);
resolver.addToIndex(fakeBuildRule);
ExplicitBuildTargetSourcePath archive1 =
new ExplicitBuildTargetSourcePath(fakeBuildRule.getBuildTarget(), Paths.get("location"));
PathSourcePath archive2 =
new PathSourcePath(new FakeProjectFilesystem(), Paths.get("otherLocation"));
// Verify that two ArchiveMemberSourcePaths with the same archive and path
assertEquals(
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key", ArchiveMemberSourcePath.of(archive1, Paths.get("location")))),
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key", ArchiveMemberSourcePath.of(archive1, Paths.get("location")))));
// Verify that just changing the archive changes the rule key
assertNotEquals(
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key", ArchiveMemberSourcePath.of(archive1, Paths.get("location")))),
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key", ArchiveMemberSourcePath.of(archive2, Paths.get("location")))));
// Verify that just changing the member path changes the rule key
assertNotEquals(
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key", ArchiveMemberSourcePath.of(archive1, Paths.get("location")))),
buildResult(
createBuilder(pathResolver, ruleFinder)
.setReflectively(
"key", ArchiveMemberSourcePath.of(archive1, Paths.get("different")))));
}
@Test
public void canAddMapsToRuleKeys() {
ImmutableMap<String, ?> map =
ImmutableMap.of("path", new FakeSourcePath("some/path"), "boolean", true);
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey key =
createBuilder(resolver, ruleFinder).setReflectively("map", map).build(RuleKey::new);
assertNotNull(key);
}
@Test
public void keysOfMapsAddedToRuleKeysDoNotNeedToBeStrings() {
ImmutableMap<?, ?> map =
ImmutableMap.of(
new FakeSourcePath("some/path"), "woohoo!", 42L, "life, the universe and everything");
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey key =
createBuilder(resolver, ruleFinder).setReflectively("map", map).build(RuleKey::new);
assertNotNull(key);
}
@Test
public void canAddRuleKeyAppendable() {
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey key =
createBuilder(resolver, ruleFinder)
.setReflectively("rule_key_appendable", new TestRuleKeyAppendable("foo"))
.build(RuleKey::new);
assertNotNull(key);
}
@Test
public void canAddListOfRuleKeyAppendable() {
ImmutableList<TestRuleKeyAppendable> list =
ImmutableList.of(new TestRuleKeyAppendable("foo"), new TestRuleKeyAppendable("bar"));
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey key =
createBuilder(resolver, ruleFinder).setReflectively("list", list).build(RuleKey::new);
assertNotNull(key);
}
@Test
public void canAddMapOfRuleKeyAppendable() {
ImmutableMap<String, TestRuleKeyAppendable> map =
ImmutableMap.of(
"foo", new TestRuleKeyAppendable("foo"),
"bar", new TestRuleKeyAppendable("bar"));
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
RuleKey key =
createBuilder(resolver, ruleFinder).setReflectively("map", map).build(RuleKey::new);
assertNotNull(key);
}
@Test
public void changingRuleKeyFieldChangesKeyWhenClassImplementsAppendToRuleKey() {
BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build();
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder);
FileHashCache hashCache =
new StackedFileHashCache(
ImmutableList.of(
DefaultFileHashCache.createDefaultFileHashCache(new FakeProjectFilesystem())));
BuildRule buildRule1 = new TestRuleKeyAppendableBuildRule(params, "foo", "bar");
BuildRule buildRule2 = new TestRuleKeyAppendableBuildRule(params, "foo", "xyzzy");
RuleKey ruleKey1 =
new DefaultRuleKeyFactory(0, hashCache, pathResolver, ruleFinder).build(buildRule1);
RuleKey ruleKey2 =
new DefaultRuleKeyFactory(0, hashCache, pathResolver, ruleFinder).build(buildRule2);
assertNotEquals(ruleKey1, ruleKey2);
}
@Test
public void changingRuleKeyFieldOfDepChangesKeyWhenClassImplementsAppendToRuleKey() {
BuildTarget target = BuildTargetFactory.newInstance("//cheese:peas");
BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build();
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder);
FileHashCache hashCache =
new StackedFileHashCache(
ImmutableList.of(
DefaultFileHashCache.createDefaultFileHashCache(new FakeProjectFilesystem())));
BuildRule buildRule1 = new TestRuleKeyAppendableBuildRule(params, "foo", "bar");
BuildRule buildRule2 = new TestRuleKeyAppendableBuildRule(params, "foo", "xyzzy");
BuildTarget parentTarget = BuildTargetFactory.newInstance("//cheese:milk");
BuildRuleParams parentParams1 =
new FakeBuildRuleParamsBuilder(parentTarget)
.setDeclaredDeps(ImmutableSortedSet.of(buildRule1))
.build();
BuildRule parentRule1 = new NoopBuildRule(parentParams1);
BuildRuleParams parentParams2 =
new FakeBuildRuleParamsBuilder(parentTarget)
.setDeclaredDeps(ImmutableSortedSet.of(buildRule2))
.build();
BuildRule parentRule2 = new NoopBuildRule(parentParams2);
RuleKey ruleKey1 =
new DefaultRuleKeyFactory(0, hashCache, pathResolver, ruleFinder).build(parentRule1);
RuleKey ruleKey2 =
new DefaultRuleKeyFactory(0, hashCache, pathResolver, ruleFinder).build(parentRule2);
assertNotEquals(ruleKey1, ruleKey2);
}
@Test
public void subclassWithNoopSetter() {
class NoopSetterRuleKeyBuilder extends UncachedRuleKeyBuilder {
public NoopSetterRuleKeyBuilder(
SourcePathRuleFinder ruleFinder,
SourcePathResolver pathResolver,
FileHashCache hashCache,
RuleKeyFactory<RuleKey> defaultRuleKeyFactory) {
super(ruleFinder, pathResolver, hashCache, defaultRuleKeyFactory);
}
@Override
protected NoopSetterRuleKeyBuilder setSourcePath(SourcePath sourcePath) {
return this;
}
}
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder);
FileHashCache hashCache = new FakeFileHashCache(ImmutableMap.of());
RuleKeyFactory<RuleKey> ruleKeyFactory =
new DefaultRuleKeyFactory(0, hashCache, pathResolver, ruleFinder);
RuleKey nullRuleKey =
new NoopSetterRuleKeyBuilder(ruleFinder, pathResolver, hashCache, ruleKeyFactory)
.build(RuleKey::new);
RuleKey noopRuleKey =
new NoopSetterRuleKeyBuilder(ruleFinder, pathResolver, hashCache, ruleKeyFactory)
.setReflectively("key", new FakeSourcePath("value"))
.build(RuleKey::new);
assertThat(noopRuleKey, is(equalTo(nullRuleKey)));
}
@Test
public void declaredDepsAndExtraDepsGenerateDifferentRuleKeys() {
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver sourcePathResolver = new SourcePathResolver(ruleFinder);
FileHashCache hashCache = new FakeFileHashCache(ImmutableMap.of());
DefaultRuleKeyFactory ruleKeyFactory =
new DefaultRuleKeyFactory(0, hashCache, sourcePathResolver, ruleFinder);
BuildTarget target = BuildTargetFactory.newInstance("//a:target");
BuildTarget depTarget = BuildTargetFactory.newInstance("//some:dep");
BuildRuleParams depParams = new FakeBuildRuleParamsBuilder(depTarget).build();
NoopBuildRule dep = new NoopBuildRule(depParams);
BuildRuleParams paramsWithDeclaredDep =
new FakeBuildRuleParamsBuilder(target).setDeclaredDeps(ImmutableSortedSet.of(dep)).build();
NoopBuildRule ruleWithDeclaredDep = new NoopBuildRule(paramsWithDeclaredDep);
BuildRuleParams paramsWithExtraDep =
new FakeBuildRuleParamsBuilder(target).setExtraDeps(ImmutableSortedSet.of(dep)).build();
NoopBuildRule ruleWithExtraDep = new NoopBuildRule(paramsWithExtraDep);
BuildRuleParams paramsWithBothDeps =
new FakeBuildRuleParamsBuilder(target)
.setDeclaredDeps(ImmutableSortedSet.of(dep))
.setExtraDeps(ImmutableSortedSet.of(dep))
.build();
NoopBuildRule ruleWithBothDeps = new NoopBuildRule(paramsWithBothDeps);
assertNotEquals(
ruleKeyFactory.build(ruleWithDeclaredDep), ruleKeyFactory.build(ruleWithExtraDep));
assertNotEquals(
ruleKeyFactory.build(ruleWithDeclaredDep), ruleKeyFactory.build(ruleWithBothDeps));
assertNotEquals(ruleKeyFactory.build(ruleWithExtraDep), ruleKeyFactory.build(ruleWithBothDeps));
}
private static class TestRuleKeyAppendable implements RuleKeyAppendable {
private final String value;
public TestRuleKeyAppendable(String value) {
this.value = value;
}
@Override
public void appendToRuleKey(RuleKeyObjectSink sink) {
sink.setReflectively("value", value)
.setReflectively("foo", "foo")
.setReflectively("bar", "bar");
}
}
private static class TestRuleKeyAppendableBuildRule extends NoopBuildRule {
private final String foo;
@SuppressWarnings("PMD.UnusedPrivateField")
@AddToRuleKey
private final String bar;
public TestRuleKeyAppendableBuildRule(BuildRuleParams buildRuleParams, String foo, String bar) {
super(buildRuleParams);
this.foo = foo;
this.bar = bar;
}
@Override
public void appendToRuleKey(RuleKeyObjectSink sink) {
sink.setReflectively("foo", foo);
}
}
private DefaultRuleKeyFactory.Builder<HashCode> createBuilder(
SourcePathResolver resolver, SourcePathRuleFinder ruleFinder) {
FileHashCache fileHashCache =
new FileHashCache() {
@Override
public void invalidate(Path path) {}
@Override
public void invalidateAll() {}
@Override
public HashCode get(Path path) {
return HashCode.fromString("deadbeef");
}
@Override
public HashCode get(ArchiveMemberPath archiveMemberPath) {
return HashCode.fromString("deadbeef");
}
@Override
public long getSize(Path path) {
return 0;
}
@Override
public void set(Path path, HashCode hashCode) {}
};
BuildTarget buildTarget = BuildTargetFactory.newInstance("//some:example");
BuildRule buildRule = new FakeBuildRule(buildTarget, resolver);
return new DefaultRuleKeyFactory(0, fileHashCache, resolver, ruleFinder)
.newBuilderForTesting(buildRule);
}
private RuleKeyResult<RuleKey> buildResult(RuleKeyBuilder<HashCode> builder) {
return ((DefaultRuleKeyFactory.Builder<HashCode>) builder).buildResult(RuleKey::new);
}
}