blob: 5c9770370e0e351f3d4bf5edb7e8c70bbdd7b440 [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 com.facebook.buck.util.BuckConstant.GEN_DIR;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import com.facebook.buck.model.BuildTarget;
import com.facebook.buck.model.BuildTargetFactory;
import com.facebook.buck.model.BuildTargetPattern;
import com.facebook.buck.parser.ApkGenruleBuildRuleFactory;
import com.facebook.buck.parser.BuildRuleFactoryParams;
import com.facebook.buck.parser.BuildTargetParser;
import com.facebook.buck.parser.NoSuchBuildTargetException;
import com.facebook.buck.parser.NonCheckingBuildRuleFactoryParams;
import com.facebook.buck.parser.ParseContext;
import com.facebook.buck.shell.Command;
import com.facebook.buck.shell.CommandRunner;
import com.facebook.buck.shell.ExecutionContext;
import com.facebook.buck.command.io.MakeCleanDirectoryCommand;
import com.facebook.buck.command.io.MkdirAndSymlinkFileCommand;
import com.facebook.buck.command.io.MkdirCommand;
import com.facebook.buck.shell.ShellCommand;
import com.facebook.buck.util.ProjectFilesystem;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import org.easymock.EasyMock;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
/**
* Unit test for {@link ApkGenrule}.
*/
public class ApkGenruleTest {
private static final Function<String, String> relativeToAbsolutePathFunction =
new Function<String, String>() {
@Override
public String apply(String path) {
return String.format("/opt/local/fbandroid/%s", path);
}
};
private void createSampleAndroidBinaryRule(Map<String, BuildRule> buildRuleIndex) {
// Create a java_binary that depends on a java_library so it is possible to create a
// java_binary rule with a classpath entry and a main class.
JavaLibraryRule androidLibraryRule =
DefaultJavaLibraryRule.newJavaLibraryRuleBuilder()
.setBuildTarget(BuildTargetFactory.newInstance("//:lib-android"))
.addSrc("java/com/facebook/util/Facebook.java")
.build(buildRuleIndex);
buildRuleIndex.put(androidLibraryRule.getFullyQualifiedName(), androidLibraryRule);
AndroidBinaryRule androidBinaryRule = (AndroidBinaryRule) AndroidBinaryRule.newAndroidBinaryRuleBuilder()
.setBuildTarget(BuildTargetFactory.newInstance("//:fb4a"))
.setManifest("AndroidManifest.xml")
.setTarget("Google Inc.:Google APIs:16")
.setKeystorePropertiesPath("keystore.properties")
.addDep("//:lib-android")
.addVisibilityPattern(BuildTargetPattern.MATCH_ALL)
.build(buildRuleIndex);
buildRuleIndex.put(androidBinaryRule.getFullyQualifiedName(), androidBinaryRule);
}
@Test
@SuppressWarnings("PMD.AvoidUsingHardCodedIP")
public void testCreateAndRunApkGenrule() throws IOException, NoSuchBuildTargetException {
Map<String, BuildRule> buildRuleIndex = Maps.newHashMap();
createSampleAndroidBinaryRule(buildRuleIndex);
Map<String, ?> instance = new ImmutableMap.Builder<String, Object>()
.put("name", "fb4a_signed")
.put("srcs", ImmutableList.<String>of("signer.py", "key.properties"))
.put("cmd", "python signer.py $APK key.properties > $OUT")
.put("apk", ":fb4a")
.put("out", "signed_fb4a.apk")
.put("deps", ImmutableList.<Object>of())
.build();
// From the Python object, create a ApkGenruleBuildRuleFactory to create a ApkGenrule.Builder
// that builds a ApkGenrule from the Python object.
BuildTargetParser parser = EasyMock.createNiceMock(BuildTargetParser.class);
EasyMock.expect(parser.parse(EasyMock.eq(":fb4a"), EasyMock.anyObject(ParseContext.class)))
.andStubReturn(BuildTargetFactory.newInstance("//:fb4a"));
EasyMock.replay(parser);
BuildTarget buildTarget = BuildTargetFactory.newInstance(
"//src/com/facebook", "sign_fb4a");
BuildRuleFactoryParams params = NonCheckingBuildRuleFactoryParams.
createNonCheckingBuildRuleFactoryParams(
instance,
parser,
buildTarget);
ApkGenruleBuildRuleFactory factory = new ApkGenruleBuildRuleFactory();
ApkGenrule.Builder builder = (ApkGenrule.Builder)factory.newInstance(params);
builder.setRelativeToAbsolutePathFunction(relativeToAbsolutePathFunction);
ApkGenrule apk_genrule = builder.build(buildRuleIndex);
// Verify all of the observers of the Genrule.
String expectedApkOutput = "/opt/local/fbandroid/" + GEN_DIR + "/src/com/facebook/sign_fb4a.apk";
assertEquals(BuildRuleType.APK_GENRULE, apk_genrule.getType());
assertEquals(expectedApkOutput,
apk_genrule.getOutputFilePath());
BuildContext buildContext = BuildContext.builder()
.setProjectRoot(EasyMock.createNiceMock(File.class))
.setDependencyGraph(EasyMock.createMock(DependencyGraph.class))
.setCommandRunner(EasyMock.createNiceMock(CommandRunner.class))
.setProjectFilesystem(EasyMock.createNiceMock(ProjectFilesystem.class))
.setJavaPackageFinder(EasyMock.createNiceMock(JavaPackageFinder.class))
.build();
List<String> inputsToCompareToOutputs = ImmutableList.of(
"src/com/facebook/signer.py", "src/com/facebook/key.properties");
assertEquals(inputsToCompareToOutputs,
apk_genrule.getInputsToCompareToOutput(buildContext));
// Verify that the shell commands that the genrule produces are correct.
List<Command> commands = apk_genrule.buildInternal(buildContext);
assertEquals(7, commands.size());
Command firstCommand = commands.get(0);
assertTrue(firstCommand instanceof ShellCommand);
ShellCommand rmCommand = (ShellCommand)firstCommand;
ExecutionContext executionContext = null;
assertEquals(
"First command should delete the output file to be written by the genrule.",
ImmutableList.of(
"rm",
"-f",
expectedApkOutput),
rmCommand.getShellCommand(executionContext));
Command secondCommand = commands.get(1);
assertTrue(secondCommand instanceof MkdirCommand);
MkdirCommand mkdirCommand = (MkdirCommand)secondCommand;
assertEquals(
"Second command should make sure the output directory exists.",
ImmutableList.of("mkdir", "-p", GEN_DIR + "/src/com/facebook/"),
mkdirCommand.getShellCommand(executionContext));
Command thirdCommand = commands.get(2);
assertTrue(thirdCommand instanceof MakeCleanDirectoryCommand);
MakeCleanDirectoryCommand secondMkdirCommand = (MakeCleanDirectoryCommand)thirdCommand;
String tempDirPath = "/opt/local/fbandroid/" + GEN_DIR + "/src/com/facebook/sign_fb4a__tmp";
assertEquals(
"Third command should make sure the temp directory exists.",
tempDirPath,
secondMkdirCommand.getPath());
Command fourthCommand = commands.get(3);
assertTrue(fourthCommand instanceof MakeCleanDirectoryCommand);
MakeCleanDirectoryCommand thirdMkdirCommand = (MakeCleanDirectoryCommand)fourthCommand;
String srcDirPath = "/opt/local/fbandroid/" + GEN_DIR + "/src/com/facebook/sign_fb4a__srcs";
assertEquals(
"Fourth command should make sure the temp directory exists.",
srcDirPath,
thirdMkdirCommand.getPath());
MkdirAndSymlinkFileCommand linkSource1 = (MkdirAndSymlinkFileCommand)commands.get(4);
assertEquals("/opt/local/fbandroid/src/com/facebook/signer.py",
linkSource1.getSource().getAbsolutePath());
assertEquals(srcDirPath + "/signer.py", linkSource1.getTarget().getAbsolutePath());
MkdirAndSymlinkFileCommand linkSource2 = (MkdirAndSymlinkFileCommand)commands.get(5);
assertEquals("/opt/local/fbandroid/src/com/facebook/key.properties",
linkSource2.getSource().getAbsolutePath());
assertEquals(srcDirPath + "/key.properties", linkSource2.getTarget().getAbsolutePath());
Command seventhCommand = commands.get(6);
assertTrue(seventhCommand instanceof ShellCommand);
ShellCommand genruleCommand = (ShellCommand)seventhCommand;
assertEquals("genrule: python signer.py $APK key.properties > $OUT",
genruleCommand.getShortName(executionContext));
assertEquals(new ImmutableMap.Builder<String, String>()
.put("SRCS", "/opt/local/fbandroid/src/com/facebook/signer.py " +
"/opt/local/fbandroid/src/com/facebook/key.properties")
.put("APK", GEN_DIR + "/fb4a.apk")
.put("DEPS", "")
.put("TMP", tempDirPath)
.put("SRCDIR", srcDirPath)
.put("OUT", expectedApkOutput).build(),
genruleCommand.getEnvironmentVariables());
assertEquals(
ImmutableList.of("/bin/bash", "-c", "python signer.py $APK key.properties > $OUT"),
genruleCommand.getShellCommand(executionContext));
EasyMock.verify(parser);
}
}