/* * Copyright 2014-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.macros; import static com.facebook.buck.rules.TestCellBuilder.createCellRoots; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.jvm.java.JavaBinaryRuleBuilder; import com.facebook.buck.jvm.java.JavaLibraryBuilder; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargetFactory; import com.facebook.buck.model.MacroException; import com.facebook.buck.rules.BinaryBuildRule; import com.facebook.buck.rules.BuildRule; import com.facebook.buck.rules.BuildRuleParams; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.CommandTool; import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer; import com.facebook.buck.rules.FakeBuildRuleParamsBuilder; import com.facebook.buck.rules.NoopBuildRule; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.SourcePathRuleFinder; import com.facebook.buck.rules.TargetGraph; import com.facebook.buck.rules.Tool; import com.facebook.buck.rules.args.SourcePathArg; import com.facebook.buck.shell.GenruleBuilder; import com.facebook.buck.testutil.FakeProjectFilesystem; import com.google.common.base.Preconditions; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSortedSet; import java.nio.file.Path; import java.nio.file.Paths; import org.hamcrest.Matchers; import org.junit.Test; public class ExecutableMacroExpanderTest { private BuildRule createSampleJavaBinaryRule(BuildRuleResolver ruleResolver) throws Exception { // 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. BuildRule javaLibrary = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//java/com/facebook/util:util")) .addSrc(Paths.get("java/com/facebook/util/ManifestGenerator.java")) .build(ruleResolver); BuildTarget buildTarget = BuildTargetFactory.newInstance("//java/com/facebook/util:ManifestGenerator"); return new JavaBinaryRuleBuilder(buildTarget) .setDeps(ImmutableSortedSet.of(javaLibrary.getBuildTarget())) .setMainClass("com.facebook.util.ManifestGenerator") .build(ruleResolver); } @Test public void testReplaceBinaryBuildRuleRefsInCmd() throws Exception { ProjectFilesystem filesystem = new FakeProjectFilesystem(); BuildRuleResolver ruleResolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); BuildTarget target = BuildTarget.builder(filesystem.getRootPath(), "//cheese", "cake").build(); createSampleJavaBinaryRule(ruleResolver); String originalCmd = "$(exe //java/com/facebook/util:ManifestGenerator) $OUT"; // Interpolate the build target in the genrule cmd string. MacroHandler macroHandler = new MacroHandler(ImmutableMap.of("exe", new ExecutableMacroExpander())); String transformedString = macroHandler.expand(target, createCellRoots(filesystem), ruleResolver, originalCmd); // Verify that the correct cmd was created. Path expectedClasspath = filesystem .getBuckPaths() .getGenDir() .resolve("java/com/facebook/util/ManifestGenerator.jar") .toAbsolutePath(); String expectedCmd = String.format("java -jar %s $OUT", expectedClasspath); assertEquals(expectedCmd, transformedString); } @Test public void testReplaceRelativeBinaryBuildRuleRefsInCmd() throws Exception { BuildRuleResolver ruleResolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); BuildRule rule = createSampleJavaBinaryRule(ruleResolver); String originalCmd = "$(exe :ManifestGenerator) $OUT"; // Interpolate the build target in the genrule cmd string. ProjectFilesystem filesystem = new FakeProjectFilesystem(); MacroHandler macroHandler = new MacroHandler(ImmutableMap.of("exe", new ExecutableMacroExpander())); String transformedString = macroHandler.expand( rule.getBuildTarget(), createCellRoots(filesystem), ruleResolver, originalCmd); // Verify that the correct cmd was created. Path expectedClasspath = filesystem .getBuckPaths() .getGenDir() .resolve("java/com/facebook/util/ManifestGenerator.jar") .toAbsolutePath(); String expectedCmd = String.format("java -jar %s $OUT", expectedClasspath); assertEquals(expectedCmd, transformedString); } @Test public void testDepsGenrule() throws Exception { BuildRuleResolver ruleResolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); BuildRule rule = createSampleJavaBinaryRule(ruleResolver); // Interpolate the build target in the genrule cmd string. String originalCmd = "$(exe :ManifestGenerator) $OUT"; ProjectFilesystem filesystem = new FakeProjectFilesystem(); MacroHandler macroHandler = new MacroHandler(ImmutableMap.of("exe", new ExecutableMacroExpander())); String transformedString = macroHandler.expand( rule.getBuildTarget(), createCellRoots(filesystem), ruleResolver, originalCmd); // Verify that the correct cmd was created. Path expectedClasspath = filesystem .getBuckPaths() .getGenDir() .resolve("java/com/facebook/util/ManifestGenerator.jar") .toAbsolutePath(); String expectedCmd = String.format("java -jar %s $OUT", expectedClasspath); assertEquals(expectedCmd, transformedString); } @Test public void testBuildTimeDependencies() throws Exception { ProjectFilesystem filesystem = new FakeProjectFilesystem(); BuildRuleResolver ruleResolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathResolver pathResolver = new SourcePathResolver(new SourcePathRuleFinder(ruleResolver)); final BuildRule dep1 = GenruleBuilder.newGenruleBuilder(BuildTargetFactory.newInstance("//:dep1")) .setOut("arg1") .build(ruleResolver, filesystem); final BuildRule dep2 = GenruleBuilder.newGenruleBuilder(BuildTargetFactory.newInstance("//:dep2")) .setOut("arg2") .build(ruleResolver, filesystem); BuildTarget target = BuildTargetFactory.newInstance("//:rule"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); ruleResolver.addToIndex( new NoopBinaryBuildRule(params) { @Override public Tool getExecutableCommand() { return new CommandTool.Builder() .addArg(SourcePathArg.of(dep1.getSourcePathToOutput())) .addArg(SourcePathArg.of(dep2.getSourcePathToOutput())) .build(); } }); // Verify that the correct cmd was created. ExecutableMacroExpander expander = new ExecutableMacroExpander(); assertThat( expander.extractBuildTimeDeps( target, createCellRoots(filesystem), ruleResolver, ImmutableList.of("//:rule")), Matchers.containsInAnyOrder(dep1, dep2)); assertThat( expander.expand( target, createCellRoots(filesystem), ruleResolver, ImmutableList.of("//:rule")), Matchers.equalTo( String.format( "%s %s", pathResolver.getAbsolutePath( Preconditions.checkNotNull(dep1.getSourcePathToOutput())), pathResolver.getAbsolutePath( Preconditions.checkNotNull(dep2.getSourcePathToOutput()))))); } @Test public void extractRuleKeyAppendable() throws MacroException { BuildRuleResolver ruleResolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); BuildTarget target = BuildTargetFactory.newInstance("//:rule"); BuildRuleParams params = new FakeBuildRuleParamsBuilder(target).build(); final Tool tool = new CommandTool.Builder().addArg("command").build(); ruleResolver.addToIndex( new NoopBinaryBuildRule(params) { @Override public Tool getExecutableCommand() { return tool; } }); ExecutableMacroExpander expander = new ExecutableMacroExpander(); assertThat( expander.extractRuleKeyAppendables( target, createCellRoots(params.getProjectFilesystem()), ruleResolver, ImmutableList.of("//:rule")), Matchers.equalTo(tool)); } private abstract static class NoopBinaryBuildRule extends NoopBuildRule implements BinaryBuildRule { public NoopBinaryBuildRule(BuildRuleParams params) { super(params); } } }