/* * Copyright 2013-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 com.facebook.buck.jvm.java.JavaCompilationConstants.ANDROID_JAVAC_OPTIONS; import static com.facebook.buck.jvm.java.JavaCompilationConstants.DEFAULT_JAVAC; import static org.junit.Assert.assertEquals; import com.facebook.buck.io.MorePaths; import com.facebook.buck.io.ProjectFilesystem; import com.facebook.buck.jvm.java.AnnotationProcessingParams; import com.facebook.buck.jvm.java.ClasspathChecker; import com.facebook.buck.jvm.java.JavacOptions; import com.facebook.buck.jvm.java.JavacOptionsAmender; import com.facebook.buck.jvm.java.JavacStep; import com.facebook.buck.jvm.java.JavacToJarStepFactory; import com.facebook.buck.jvm.java.NoOpClassUsageFileWriter; import com.facebook.buck.model.BuildTargetFactory; import com.facebook.buck.model.BuildTargets; import com.facebook.buck.rules.BuildRule; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer; import com.facebook.buck.rules.FakeBuildContext; import com.facebook.buck.rules.FakeBuildRuleParamsBuilder; import com.facebook.buck.rules.FakeBuildableContext; import com.facebook.buck.rules.FakeSourcePath; import com.facebook.buck.rules.SourcePathResolver; import com.facebook.buck.rules.SourcePathRuleFinder; import com.facebook.buck.rules.TargetGraph; import com.facebook.buck.step.Step; import com.facebook.buck.step.TestExecutionContext; import com.facebook.buck.testutil.FakeProjectFilesystem; import com.facebook.buck.testutil.MoreAsserts; import com.facebook.buck.util.MoreCollectors; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedSet; import java.io.IOException; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Optional; import java.util.stream.Stream; import org.junit.Test; public class DummyRDotJavaTest { @Test public void testBuildSteps() throws IOException { ProjectFilesystem filesystem = new FakeProjectFilesystem(); BuildRuleResolver ruleResolver = new BuildRuleResolver(TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder(ruleResolver); SourcePathResolver pathResolver = new SourcePathResolver(ruleFinder); BuildRule resourceRule1 = ruleResolver.addToIndex( AndroidResourceRuleBuilder.newBuilder() .setRuleFinder(ruleFinder) .setBuildTarget(BuildTargetFactory.newInstance("//android_res/com/example:res1")) .setRDotJavaPackage("com.facebook") .setRes(new FakeSourcePath("android_res/com/example/res1")) .build()); setAndroidResourceBuildOutput(resourceRule1); BuildRule resourceRule2 = ruleResolver.addToIndex( AndroidResourceRuleBuilder.newBuilder() .setRuleFinder(ruleFinder) .setBuildTarget(BuildTargetFactory.newInstance("//android_res/com/example:res2")) .setRDotJavaPackage("com.facebook") .setRes(new FakeSourcePath("android_res/com/example/res2")) .build()); setAndroidResourceBuildOutput(resourceRule2); DummyRDotJava dummyRDotJava = new DummyRDotJava( new FakeBuildRuleParamsBuilder(BuildTargetFactory.newInstance("//java/base:rule")) .setProjectFilesystem(filesystem) .build(), ruleFinder, ImmutableSet.of( (HasAndroidResourceDeps) resourceRule1, (HasAndroidResourceDeps) resourceRule2), new JavacToJarStepFactory( DEFAULT_JAVAC, ANDROID_JAVAC_OPTIONS, JavacOptionsAmender.IDENTITY), /* forceFinalResourceIds */ false, Optional.empty(), Optional.of("R2"), false); FakeBuildableContext buildableContext = new FakeBuildableContext(); List<Step> steps = dummyRDotJava.getBuildSteps(FakeBuildContext.NOOP_CONTEXT, buildableContext); assertEquals("DummyRDotJava returns an incorrect number of Steps.", 12, steps.size()); String rDotJavaSrcFolder = BuildTargets.getScratchPath( filesystem, dummyRDotJava.getBuildTarget(), "__%s_rdotjava_src__") .toString(); String rDotJavaBinFolder = BuildTargets.getScratchPath( filesystem, dummyRDotJava.getBuildTarget(), "__%s_rdotjava_bin__") .toString(); String rDotJavaOutputFolder = BuildTargets.getGenPath( filesystem, dummyRDotJava.getBuildTarget(), "__%s_dummyrdotjava_output__") .toString(); String rDotJavaOutputJar = MorePaths.pathWithPlatformSeparators( String.format( "%s/%s.jar", rDotJavaOutputFolder, dummyRDotJava.getBuildTarget().getShortNameAndFlavorPostfix())); String genFolder = Paths.get("buck-out/gen/java/base/").toString(); List<String> sortedSymbolsFiles = Stream.of((AndroidResource) resourceRule1, (AndroidResource) resourceRule2) .map(Object::toString) .collect(MoreCollectors.toImmutableList()); ImmutableSortedSet<Path> javaSourceFiles = ImmutableSortedSet.of(Paths.get(rDotJavaSrcFolder).resolve("com/facebook/R.java")); List<String> expectedStepDescriptions = new ImmutableList.Builder<String>() .addAll(makeCleanDirDescription(filesystem.resolve(rDotJavaSrcFolder))) .add("android-res-merge " + Joiner.on(' ').join(sortedSymbolsFiles)) .add("android-res-merge " + Joiner.on(' ').join(sortedSymbolsFiles)) .addAll(makeCleanDirDescription(filesystem.resolve(rDotJavaBinFolder))) .addAll(makeCleanDirDescription(filesystem.resolve(rDotJavaOutputFolder))) .add(String.format("mkdir -p %s", filesystem.resolve(genFolder))) .add( new JavacStep( Paths.get(rDotJavaBinFolder), NoOpClassUsageFileWriter.instance(), Optional.empty(), javaSourceFiles, BuildTargets.getGenPath( filesystem, dummyRDotJava.getBuildTarget(), "__%s__srcs"), /* declared classpath */ ImmutableSortedSet.of(), DEFAULT_JAVAC, JavacOptions.builder(ANDROID_JAVAC_OPTIONS) .setAnnotationProcessingParams(AnnotationProcessingParams.EMPTY) .build(), null, pathResolver, new FakeProjectFilesystem(), new ClasspathChecker(), /* directToJarOutputSettings */ Optional.empty()) .getDescription(TestExecutionContext.newInstance())) .add(String.format("jar cf %s %s", rDotJavaOutputJar, rDotJavaBinFolder)) .add(String.format("check_dummy_r_jar_not_empty %s", rDotJavaOutputJar)) .build(); MoreAsserts.assertSteps( "DummyRDotJava.getBuildSteps() must return these exact steps.", expectedStepDescriptions, steps, TestExecutionContext.newInstance()); assertEquals( ImmutableSet.of(Paths.get(rDotJavaBinFolder), Paths.get(rDotJavaOutputJar)), buildableContext.getRecordedArtifacts()); } @Test public void testRDotJavaBinFolder() { SourcePathRuleFinder ruleFinder = new SourcePathRuleFinder( new BuildRuleResolver( TargetGraph.EMPTY, new DefaultTargetNodeToBuildRuleTransformer())); DummyRDotJava dummyRDotJava = new DummyRDotJava( new FakeBuildRuleParamsBuilder( BuildTargetFactory.newInstance("//java/com/example:library")) .build(), ruleFinder, ImmutableSet.of(), new JavacToJarStepFactory( DEFAULT_JAVAC, ANDROID_JAVAC_OPTIONS, JavacOptionsAmender.IDENTITY), /* forceFinalResourceIds */ false, Optional.empty(), Optional.empty(), false); assertEquals( BuildTargets.getScratchPath( dummyRDotJava.getProjectFilesystem(), dummyRDotJava.getBuildTarget(), "__%s_rdotjava_bin__"), dummyRDotJava.getRDotJavaBinFolder()); } private static ImmutableList<String> makeCleanDirDescription(Path dirname) { return ImmutableList.of( String.format("rm -f -r %s", dirname), String.format("mkdir -p %s", dirname)); } private void setAndroidResourceBuildOutput(BuildRule resourceRule) { if (resourceRule instanceof AndroidResource) { ((AndroidResource) resourceRule).getBuildOutputInitializer(); } } }