/* * Copyright 2015-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.easymock.EasyMock.createMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; import static org.hamcrest.junit.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; import com.facebook.buck.event.BuckEventBusFactory; import com.facebook.buck.jvm.core.JavaPackageFinder; import com.facebook.buck.jvm.java.JavaBuckConfig; import com.facebook.buck.jvm.java.JavaLibrary; import com.facebook.buck.jvm.java.JavaLibraryBuilder; import com.facebook.buck.jvm.java.JavaLibraryDescription; import com.facebook.buck.jvm.java.JavaLibraryDescriptionArg; import com.facebook.buck.jvm.java.JavacOptions; import com.facebook.buck.jvm.java.testutil.AbiCompilationModeTest; import com.facebook.buck.model.BuildTarget; import com.facebook.buck.model.BuildTargetFactory; import com.facebook.buck.rules.ActionGraph; import com.facebook.buck.rules.BuildContext; import com.facebook.buck.rules.BuildRule; import com.facebook.buck.rules.BuildRuleResolver; import com.facebook.buck.rules.DefaultTargetNodeToBuildRuleTransformer; import com.facebook.buck.rules.FakeBuildRule; 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.query.Query; import com.facebook.buck.testutil.TargetGraphFactory; import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSortedSet; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; import java.util.Optional; import org.hamcrest.Matchers; import org.junit.Before; import org.junit.Test; public class AndroidLibraryDescriptionTest extends AbiCompilationModeTest { private JavaBuckConfig javaBuckConfig; @Before public void setUp() { javaBuckConfig = getJavaBuckConfigWithCompilationMode(); } @Test public void rulesExportedFromDepsBecomeFirstOrderDeps() throws Exception { TargetNode<?, ?> transitiveExportedNode = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//:transitive_exported_rule"), javaBuckConfig) .addSrc(Paths.get("java/src/com/transitive/hi.java")) .build(); TargetNode<?, ?> exportedNode = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//:exported_rule"), javaBuckConfig) .addSrc(Paths.get("java/src/com/exported_rule/foo.java")) .addExportedDep(transitiveExportedNode.getBuildTarget()) .build(); TargetNode<?, ?> exportingNode = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//:exporting_rule"), javaBuckConfig) .addSrc(Paths.get("java/src/com/exporting_rule/bar.java")) .addExportedDep(exportedNode.getBuildTarget()) .build(); TargetNode<?, ?> androidLibNode = AndroidLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//:rule"), javaBuckConfig) .addDep(exportingNode.getBuildTarget()) .build(); TargetGraph targetGraph = TargetGraphFactory.newInstance( transitiveExportedNode, exportedNode, exportingNode, androidLibNode); BuildRuleResolver resolver = new BuildRuleResolver(targetGraph, new DefaultTargetNodeToBuildRuleTransformer()); BuildRule androidLibRule = resolver.requireRule(androidLibNode.getBuildTarget()); BuildRule exportedRule = resolver.requireRule(exportedNode.getBuildTarget()); BuildRule transitiveExportedRule = resolver.requireRule(transitiveExportedNode.getBuildTarget()); // First order deps should become CalculateAbi rules if we're compiling against ABIs if (compileAgainstAbis.equals(TRUE)) { exportedRule = resolver.getRule(((JavaLibrary) exportedRule).getAbiJar().get()); transitiveExportedRule = resolver.getRule(((JavaLibrary) transitiveExportedRule).getAbiJar().get()); } assertThat( androidLibRule.getBuildDeps(), Matchers.allOf(Matchers.hasItem(exportedRule), Matchers.hasItem(transitiveExportedRule))); } @Test public void rulesMatchingDepQueryBecomeFirstOrderDeps() throws Exception { // Set up target graph: rule -> lib -> sublib -> bottom TargetNode<JavaLibraryDescriptionArg, JavaLibraryDescription> bottomNode = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//:bottom"), javaBuckConfig) .build(); TargetNode<JavaLibraryDescriptionArg, JavaLibraryDescription> sublibNode = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//:sublib"), javaBuckConfig) .addDep(bottomNode.getBuildTarget()) .build(); TargetNode<JavaLibraryDescriptionArg, JavaLibraryDescription> libNode = JavaLibraryBuilder.createBuilder(BuildTargetFactory.newInstance("//:lib"), javaBuckConfig) .addDep(sublibNode.getBuildTarget()) .build(); TargetGraph targetGraph = TargetGraphFactory.newInstance(bottomNode, libNode, sublibNode); BuildRuleResolver resolver = new BuildRuleResolver(targetGraph, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathResolver pathResolver = new SourcePathResolver(new SourcePathRuleFinder(resolver)); FakeBuildRule bottomRule = resolver.addToIndex(new FakeBuildRule(bottomNode.getBuildTarget(), pathResolver)); FakeBuildRule sublibRule = resolver.addToIndex( new FakeBuildRule( sublibNode.getBuildTarget(), pathResolver, ImmutableSortedSet.of(bottomRule))); FakeBuildRule libRule = resolver.addToIndex( new FakeBuildRule( libNode.getBuildTarget(), pathResolver, ImmutableSortedSet.of(sublibRule))); BuildTarget target = BuildTargetFactory.newInstance("//:rule"); BuildRule javaLibrary = AndroidLibraryBuilder.createBuilder(target, javaBuckConfig) .addDep(libNode.getBuildTarget()) .setDepsQuery(Query.of("filter('.*lib', deps($declared_deps))")) .build(resolver, targetGraph); assertThat(javaLibrary.getBuildDeps(), Matchers.hasItems(libRule, sublibRule)); // The bottom rule should be filtered since it does not match the regex assertThat(javaLibrary.getBuildDeps(), Matchers.not(Matchers.hasItem(bottomRule))); } @Test public void rulesExportedFromProvidedDepsBecomeFirstOrderDeps() throws Exception { TargetNode<?, ?> transitiveExportedNode = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//:transitive_exported_rule"), javaBuckConfig) .addSrc(Paths.get("java/src/com/transitive/hi.java")) .build(); TargetNode<?, ?> exportedNode = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//:exported_rule"), javaBuckConfig) .addSrc(Paths.get("java/src/com/exported_rule/foo.java")) .addExportedDep(transitiveExportedNode.getBuildTarget()) .build(); TargetNode<?, ?> exportingNode = JavaLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//:exporting_rule"), javaBuckConfig) .addSrc(Paths.get("java/src/com/exporting_rule/bar.java")) .addExportedDep(exportedNode.getBuildTarget()) .build(); TargetNode<?, ?> androidLibNode = AndroidLibraryBuilder.createBuilder( BuildTargetFactory.newInstance("//:rule"), javaBuckConfig) .addProvidedDep(exportingNode.getBuildTarget()) .build(); TargetGraph targetGraph = TargetGraphFactory.newInstance( transitiveExportedNode, exportedNode, exportingNode, androidLibNode); BuildRuleResolver resolver = new BuildRuleResolver(targetGraph, new DefaultTargetNodeToBuildRuleTransformer()); BuildRule androidLibRule = resolver.requireRule(androidLibNode.getBuildTarget()); BuildRule exportedRule = resolver.requireRule(exportedNode.getBuildTarget()); BuildRule transitiveExportedRule = resolver.requireRule(transitiveExportedNode.getBuildTarget()); // First order deps should become CalculateAbi rules if we're compiling against ABIs if (compileAgainstAbis.equals(TRUE)) { exportedRule = resolver.getRule(((JavaLibrary) exportedRule).getAbiJar().get()); transitiveExportedRule = resolver.getRule(((JavaLibrary) transitiveExportedRule).getAbiJar().get()); } assertThat( androidLibRule.getBuildDeps(), Matchers.allOf(Matchers.hasItem(exportedRule), Matchers.hasItem(transitiveExportedRule))); } @Test public void bootClasspathAppenderAddsLibsFromAndroidPlatformTarget() { BuildContext.Builder builder = BuildContext.builder(); // Set to non-null values. builder.setActionGraph(createMock(ActionGraph.class)); builder.setSourcePathResolver(createMock(SourcePathResolver.class)); builder.setJavaPackageFinder(createMock(JavaPackageFinder.class)); builder.setEventBus(BuckEventBusFactory.newInstance()); AndroidPlatformTarget androidPlatformTarget = createMock(AndroidPlatformTarget.class); List<Path> entries = ImmutableList.of( Paths.get("add-ons/addon-google_apis-google-15/libs/effects.jar"), Paths.get("add-ons/addon-google_apis-google-15/libs/maps.jar"), Paths.get("add-ons/addon-google_apis-google-15/libs/usb.jar")); expect(androidPlatformTarget.getBootclasspathEntries()).andReturn(entries); replay(androidPlatformTarget); builder.setAndroidPlatformTargetSupplier(Suppliers.ofInstance(androidPlatformTarget)); BootClasspathAppender appender = new BootClasspathAppender(); JavacOptions options = JavacOptions.builder().setSourceLevel("1.7").setTargetLevel("1.7").build(); JavacOptions updated = appender.amend(options, builder.build()); assertEquals( Optional.of( ("add-ons/addon-google_apis-google-15/libs/effects.jar" + File.pathSeparatorChar + "add-ons/addon-google_apis-google-15/libs/maps.jar" + File.pathSeparatorChar + "add-ons/addon-google_apis-google-15/libs/usb.jar") .replace("/", File.separator)), updated.getBootclasspath()); verify(androidPlatformTarget); } @Test public void testClasspathContainsOnlyJavaTargets() throws Exception { TargetNode<AndroidResourceDescriptionArg, AndroidResourceDescription> resourceRule = AndroidResourceBuilder.createBuilder(BuildTargetFactory.newInstance("//:res")).build(); TargetGraph targetGraph = TargetGraphFactory.newInstance(resourceRule); BuildRuleResolver resolver = new BuildRuleResolver(targetGraph, new DefaultTargetNodeToBuildRuleTransformer()); SourcePathResolver pathResolver = new SourcePathResolver(new SourcePathRuleFinder(resolver)); resolver.addToIndex(new FakeBuildRule(resourceRule.getBuildTarget(), pathResolver)); AndroidLibrary androidLibrary = AndroidLibraryBuilder.createBuilder(BuildTargetFactory.newInstance("//:android_lib")) .addDep(resourceRule.getBuildTarget()) .build(resolver, targetGraph); assertThat(androidLibrary.getCompileTimeClasspathSourcePaths(), Matchers.empty()); } }