/*
* 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.android;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import com.facebook.buck.io.ProjectFilesystem;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.rules.BuildRule;
import com.facebook.buck.rules.BuildRuleParams;
import com.facebook.buck.rules.BuildRuleResolver;
import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer;
import com.facebook.buck.rules.FakeBuildRuleParamsBuilder;
import com.facebook.buck.rules.FakeOnDiskBuildInfo;
import com.facebook.buck.rules.FakeSourcePath;
import com.facebook.buck.rules.PathSourcePath;
import com.facebook.buck.rules.RuleKey;
import com.facebook.buck.rules.SourcePathResolver;
import com.facebook.buck.rules.SourcePathRuleFinder;
import com.facebook.buck.rules.TargetGraph;
import com.facebook.buck.rules.TargetNode;
import com.facebook.buck.rules.keys.DefaultRuleKeyFactory;
import com.facebook.buck.rules.keys.InputBasedRuleKeyFactory;
import com.facebook.buck.testutil.FakeFileHashCache;
import com.facebook.buck.testutil.FakeProjectFilesystem;
import com.facebook.buck.testutil.TargetGraphFactory;
import com.facebook.buck.util.cache.DefaultFileHashCache;
import com.facebook.buck.util.cache.FileHashCache;
import com.facebook.buck.util.cache.StackedFileHashCache;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Function;
import org.hamcrest.Matchers;
import org.junit.Test;
public class AndroidResourceTest {
@Test
public void testRuleKeyForDifferentInputFilenames() throws Exception {
BuildTarget buildTarget = BuildTargetFactory.newInstance("//java/src/com/facebook/base:res");
Function<Path, BuildRuleResolver> createResourceRule =
(Path resourcePath) -> {
FakeProjectFilesystem projectFilesystem = new FakeProjectFilesystem();
projectFilesystem.createNewFile(resourcePath);
projectFilesystem.createNewFile(
Paths.get("java/src/com/facebook/base/assets/drawable/B.xml"));
TargetNode<?, ?> resourceNode =
AndroidResourceBuilder.createBuilder(buildTarget, projectFilesystem)
.setRes(new FakeSourcePath(projectFilesystem, "java/src/com/facebook/base/res"))
.setRDotJavaPackage("com.facebook")
.setAssets(
new FakeSourcePath(projectFilesystem, "java/src/com/facebook/base/assets"))
.setManifest(
new PathSourcePath(
projectFilesystem,
Paths.get("java/src/com/facebook/base/AndroidManifest.xml")))
.build();
TargetGraph targetGraph = TargetGraphFactory.newInstance(resourceNode);
return new BuildRuleResolver(targetGraph, new DefaultTargetNodeToBuildRuleTransformer());
};
FakeFileHashCache hashCache =
FakeFileHashCache.createFromStrings(
ImmutableMap.of(
"java/src/com/facebook/base/AndroidManifest.xml", "bbbbbbbbbb",
"java/src/com/facebook/base/assets/drawable/B.xml", "aaaaaaaaaaaa",
"java/src/com/facebook/base/res/drawable/A.xml", "dddddddddd",
"java/src/com/facebook/base/res/drawable/C.xml", "eeeeeeeeee"));
BuildRuleResolver resolver1 =
createResourceRule.apply(Paths.get("java/src/com/facebook/base/res/drawable/A.xml"));
BuildRuleResolver resolver2 =
createResourceRule.apply(Paths.get("java/src/com/facebook/base/res/drawable/C.xml"));
BuildRule androidResource1 = resolver1.requireRule(buildTarget);
SourcePathRuleFinder ruleFinder1 = new SourcePathRuleFinder(resolver1);
SourcePathResolver pathResolver1 = new SourcePathResolver(ruleFinder1);
BuildRule androidResource2 = resolver2.requireRule(buildTarget);
SourcePathRuleFinder ruleFinder2 = new SourcePathRuleFinder(resolver2);
SourcePathResolver pathResolver2 = new SourcePathResolver(ruleFinder2);
RuleKey ruleKey1 =
new DefaultRuleKeyFactory(0, hashCache, pathResolver1, ruleFinder1).build(androidResource1);
RuleKey ruleKey2 =
new DefaultRuleKeyFactory(0, hashCache, pathResolver2, ruleFinder2).build(androidResource2);
assertNotEquals(
"The two android_resource rules should have different rule keys.", ruleKey1, ruleKey2);
}
@Test
public void testGetRDotJavaPackageWhenPackageIsSpecified() throws IOException {
ProjectFilesystem projectFilesystem = FakeProjectFilesystem.createRealTempFilesystem();
BuildTarget buildTarget =
BuildTargetFactory.newInstance(
projectFilesystem.getRootPath(), "//java/src/com/facebook/base:res");
BuildRuleParams params =
new FakeBuildRuleParamsBuilder(buildTarget).setProjectFilesystem(projectFilesystem).build();
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
AndroidResource androidResource =
new AndroidResource(
params,
ruleFinder,
/* deps */ ImmutableSortedSet.of(),
new FakeSourcePath("foo/res"),
ImmutableSortedMap.of(
Paths.get("values/strings.xml"), new FakeSourcePath("foo/res/values/strings.xml")),
/* rDotJavaPackage */ "com.example.android",
/* assets */ null,
/* assetsSrcs */ ImmutableSortedMap.of(),
/* manifestFile */ null,
/* hasWhitelistedStrings */ false);
projectFilesystem.writeContentsToPath(
"com.example.android\n",
resolver.getRelativePath(androidResource.getPathToRDotJavaPackageFile()));
FakeOnDiskBuildInfo onDiskBuildInfo = new FakeOnDiskBuildInfo();
androidResource.initializeFromDisk(onDiskBuildInfo);
assertEquals("com.example.android", androidResource.getRDotJavaPackage());
}
@Test
public void testGetRDotJavaPackageWhenPackageIsNotSpecified() throws IOException {
ProjectFilesystem projectFilesystem = FakeProjectFilesystem.createRealTempFilesystem();
BuildTarget buildTarget =
BuildTargetFactory.newInstance(
projectFilesystem.getRootPath(), "//java/src/com/facebook/base:res");
BuildRuleParams params =
new FakeBuildRuleParamsBuilder(buildTarget).setProjectFilesystem(projectFilesystem).build();
SourcePathRuleFinder ruleFinder =
new SourcePathRuleFinder(
new BuildRuleResolver(
TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()));
SourcePathResolver resolver = new SourcePathResolver(ruleFinder);
AndroidResource androidResource =
new AndroidResource(
params,
ruleFinder,
/* deps */ ImmutableSortedSet.of(),
new FakeSourcePath("foo/res"),
ImmutableSortedMap.of(
Paths.get("values/strings.xml"), new FakeSourcePath("foo/res/values/strings.xml")),
/* rDotJavaPackage */ null,
/* assets */ null,
/* assetsSrcs */ ImmutableSortedMap.of(),
/* manifestFile */ new PathSourcePath(
projectFilesystem, Paths.get("foo/AndroidManifest.xml")),
/* hasWhitelistedStrings */ false);
projectFilesystem.writeContentsToPath(
"com.ex.pkg\n", resolver.getRelativePath(androidResource.getPathToRDotJavaPackageFile()));
FakeOnDiskBuildInfo onDiskBuildInfo = new FakeOnDiskBuildInfo();
androidResource.initializeFromDisk(onDiskBuildInfo);
assertEquals("com.ex.pkg", androidResource.getRDotJavaPackage());
}
@Test
public void testInputRuleKeyChangesIfDependencySymbolsChanges() throws Exception {
ProjectFilesystem filesystem = new FakeProjectFilesystem();
TargetNode<?, ?> depNode =
AndroidResourceBuilder.createBuilder(BuildTargetFactory.newInstance("//:dep"), filesystem)
.setManifest(new FakeSourcePath("manifest"))
.setRes(Paths.get("res"))
.build();
TargetNode<?, ?> resourceNode =
AndroidResourceBuilder.createBuilder(BuildTargetFactory.newInstance("//:rule"), filesystem)
.setDeps(ImmutableSortedSet.of(depNode.getBuildTarget()))
.build();
TargetGraph targetGraph = TargetGraphFactory.newInstance(depNode, resourceNode);
BuildRuleResolver resolver =
new BuildRuleResolver(targetGraph, new DefaultTargetNodeToBuildRuleTransformer());
AndroidResource dep = (AndroidResource) resolver.requireRule(depNode.getBuildTarget());
AndroidResource resource =
(AndroidResource) resolver.requireRule(resourceNode.getBuildTarget());
SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(resolver);
SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder);
FileHashCache fileHashCache =
new StackedFileHashCache(
ImmutableList.of(DefaultFileHashCache.createDefaultFileHashCache(filesystem)));
filesystem.writeContentsToPath(
"something", pathResolver.getRelativePath(dep.getPathToTextSymbolsFile()));
RuleKey original =
new InputBasedRuleKeyFactory(0, fileHashCache, pathResolver, ruleFinder).build(resource);
fileHashCache.invalidateAll();
filesystem.writeContentsToPath(
"something else", pathResolver.getRelativePath(dep.getPathToTextSymbolsFile()));
RuleKey changed =
new InputBasedRuleKeyFactory(0, fileHashCache, pathResolver, ruleFinder).build(resource);
assertThat(original, Matchers.not(Matchers.equalTo(changed)));
}
}