diff options
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBinaryTest.java')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBinaryTest.java | 918 |
1 files changed, 918 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBinaryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBinaryTest.java new file mode 100644 index 0000000000..c167d312b5 --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcBinaryTest.java @@ -0,0 +1,918 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// 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.google.devtools.build.lib.rules.objc; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.devtools.build.lib.rules.objc.BinaryLinkingTargetFactory.REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE; +import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.APP_ICON_ATTR; +import static com.google.devtools.build.lib.rules.objc.ObjcRuleClasses.ReleaseBundlingRule.LAUNCH_IMAGE_ATTR; + +import com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableListMultimap; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMultiset; +import com.google.common.collect.ImmutableSetMultimap; +import com.google.common.collect.Multiset; +import com.google.devtools.build.lib.actions.Action; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.actions.CommandAction; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.RunfilesProvider; +import com.google.devtools.build.lib.analysis.actions.SpawnAction; +import com.google.devtools.build.lib.analysis.config.CompilationMode; +import com.google.devtools.build.lib.packages.util.MockObjcSupport; +import com.google.devtools.build.lib.packages.util.MockProtoSupport; +import com.google.devtools.build.lib.rules.objc.CompilationSupport.ExtraLinkArgs; +import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos; +import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.BundleFile; +import com.google.devtools.build.xcode.bundlemerge.proto.BundleMergeProtos.MergeZip; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test case for objc_binary. */ +@RunWith(JUnit4.class) +public class ObjcBinaryTest extends ObjcRuleTestCase { + static final RuleType RULE_TYPE = new BinaryRuleType("objc_binary"); + + protected ConfiguredTarget addMockBinAndLibs(List<String> srcs) throws Exception { + createLibraryTargetWriter("//lib1:lib1") + .setAndCreateFiles("srcs", "a.m", "b.m", "private.h") + .setAndCreateFiles("hdrs", "hdr.h") + .write(); + createLibraryTargetWriter("//lib2:lib2") + .setAndCreateFiles("srcs", "a.m", "b.m", "private.h") + .setAndCreateFiles("hdrs", "hdr.h") + .write(); + + return createBinaryTargetWriter("//bin:bin") + .setAndCreateFiles("srcs", srcs) + .setList("deps", "//lib1:lib1", "//lib2:lib2") + .write(); + } + + @Before + public final void initializeToolsConfigMock() throws Exception { + MockProtoSupport.setup(mockToolsConfig); + MockObjcSupport.setupObjcProto(mockToolsConfig); + } + + @Test + public void testCreate_runfiles() throws Exception { + ConfiguredTarget binary = addMockBinAndLibs(ImmutableList.of("a.m")); + RunfilesProvider runfiles = binary.getProvider(RunfilesProvider.class); + assertThat(runfiles.getDefaultRunfiles().getArtifacts()).isEmpty(); + assertThat(Artifact.toRootRelativePaths(runfiles.getDataRunfiles().getArtifacts())) + .containsExactly( + "bin/bin.ipa", + "bin/bin_bin"); + } + + @Test + public void testFilesToRun() throws Exception { + checkFilesToRun(RULE_TYPE); + } + + @Test + public void testNoRunfilesSupportForDevice() throws Exception { + checkNoRunfilesSupportForDevice(RULE_TYPE); + } + + @Test + public void testGenerateRunnerScriptAction() throws Exception { + checkGenerateRunnerScriptAction(RULE_TYPE); + } + + @Test + public void testGenerateRunnerScriptAction_escaped() throws Exception { + checkGenerateRunnerScriptAction_escaped(RULE_TYPE); + } + + @Test + public void testLinkActionDuplicateInputs() throws Exception { + checkLinkActionDuplicateInputs(RULE_TYPE, new ExtraLinkArgs()); + } + + @Test + /** + * Tests that bitcode is disabled for simulator builds even if enabled by flag. + */ + public void testLinkActionsWithBitcode_simulator() throws Exception { + useConfiguration("--xcode_version=7.1", "--apple_bitcode=embedded", + "--ios_multi_cpus=x86_64"); + createBinaryTargetWriter("//objc:bin").setAndCreateFiles("srcs", "a.m").write(); + + CommandAction linkAction = linkAction("//objc:bin"); + + String commandLine = Joiner.on(" ").join(linkAction.getArguments()); + assertThat(commandLine).doesNotContain("-fembed-bitcode"); + assertThat(commandLine).doesNotContain("-fembed-bitcode-marker"); + } + + @Test + public void testLinkActionsWithNoBitcode() throws Exception { + useConfiguration("--xcode_version=7.1", "--apple_bitcode=none", + "--ios_multi_cpus=arm64"); + createBinaryTargetWriter("//objc:bin").setAndCreateFiles("srcs", "a.m").write(); + + CommandAction linkAction = linkAction("//objc:bin"); + + String commandLine = Joiner.on(" ").join(linkAction.getArguments()); + assertThat(commandLine).doesNotContain("-fembed-bitcode"); + assertThat(commandLine).doesNotContain("-fembed-bitcode-marker"); + } + + @Test + public void testSigningAction() throws Exception { + checkDeviceSigningAction(RULE_TYPE); + } + + @Test + public void testSigningWithCertName() throws Exception { + checkSigningWithCertName(RULE_TYPE); + } + + @Test + public void testProvisioningProfile_simulatorBuild() throws Exception { + useConfiguration("--cpu=ios_i386"); + addMockBinAndLibs(ImmutableList.of("a.m")); + + Artifact provisioningProfile = + getFileConfiguredTarget("//tools/objc:foo.mobileprovision").getArtifact(); + SpawnAction spawnAction = bundleMergeAction("//bin:bin"); + assertThat(spawnAction.getInputs()).doesNotContain(provisioningProfile); + + BundleMergeProtos.Control control = bundleMergeControl("//bin:bin"); + assertThat(mobileProvisionProfiles(control)).isEmpty(); + } + + @Test + public void testProvisioningProfile_deviceBuild() throws Exception { + useConfiguration("--cpu=ios_armv7"); + + addMockBinAndLibs(ImmutableList.of("a.m")); + + Artifact provisioningProfile = + getFileConfiguredTarget("//tools/objc:foo.mobileprovision").getArtifact(); + SpawnAction spawnAction = bundleMergeAction("//bin:bin"); + assertThat(spawnAction.getInputs()).contains(provisioningProfile); + + BundleMergeProtos.Control control = bundleMergeControl("//bin:bin"); + Map<String, String> profiles = mobileProvisionProfiles(control); + ImmutableMap<String, String> expectedProfiles = ImmutableMap.of( + provisioningProfile.getExecPathString(), + ReleaseBundlingSupport.PROVISIONING_PROFILE_BUNDLE_FILE); + assertThat(profiles).isEqualTo(expectedProfiles); + } + + @Test + public void testUserSpecifiedProvisioningProfile_deviceBuild() throws Exception { + useConfiguration("--cpu=ios_armv7"); + scratch.file("custom/BUILD", "exports_files(['pp.mobileprovision'])"); + scratch.file("custom/pp.mobileprovision"); + createLibraryTargetWriter("//lib1:lib1") + .setAndCreateFiles("srcs", "a.m", "b.m", "private.h") + .setAndCreateFiles("hdrs", "hdr.h") + .write(); + createLibraryTargetWriter("//lib2:lib2") + .setAndCreateFiles("srcs", "a.m", "b.m", "private.h") + .setAndCreateFiles("hdrs", "hdr.h") + .write(); + createBinaryTargetWriter("//bin:bin") + .setAndCreateFiles("srcs", "a.m") + .setList("deps", "//lib1:lib1", "//lib2:lib2") + .set("provisioning_profile", "'//custom:pp.mobileprovision'") + .write(); + + Artifact defaultProvisioningProfile = + getFileConfiguredTarget("//tools/objc:foo.mobileprovision").getArtifact(); + Artifact customProvisioningProfile = + getFileConfiguredTarget("//custom:pp.mobileprovision").getArtifact(); + SpawnAction spawnAction = bundleMergeAction("//bin:bin"); + assertThat(spawnAction.getInputs()).contains(customProvisioningProfile); + assertThat(spawnAction.getInputs()).doesNotContain(defaultProvisioningProfile); + + BundleMergeProtos.Control control = bundleMergeControl("//bin:bin"); + Map<String, String> profiles = mobileProvisionProfiles(control); + Map<String, String> expectedProfiles = ImmutableMap.of( + customProvisioningProfile.getExecPathString(), + ReleaseBundlingSupport.PROVISIONING_PROFILE_BUNDLE_FILE); + assertThat(profiles).isEqualTo(expectedProfiles); + } + + @Test + public void testCreate_mergeControlAction() throws Exception { + createLibraryTargetWriter("//lib1:lib1") + .setAndCreateFiles("srcs", "a.m", "b.m", "private.h") + .setAndCreateFiles("hdrs", "hdr.h") + .write(); + createLibraryTargetWriter("//lib2:lib2") + .setAndCreateFiles("srcs", "a.m", "b.m", "private.h") + .setAndCreateFiles("hdrs", "hdr.h") + .write(); + createBinaryTargetWriter("//bin:bin") + .setAndCreateFiles("srcs", "a.m") + .setList("deps", "//lib1:lib1", "//lib2:lib2") + .set("infoplist", "'bin-Info.plist'") + .write(); + + Action mergeAction = bundleMergeAction("//bin:bin"); + Action action = bundleMergeControlAction("//bin:bin"); + assertThat(action.getInputs()).isEmpty(); + assertThat(Artifact.toRootRelativePaths(action.getOutputs())).containsExactly( + "bin/bin.ipa-control"); + assertThat(bundleMergeControl("//bin:bin")) + .isEqualTo( + BundleMergeProtos.Control.newBuilder() + .addBundleFile( + BundleFile.newBuilder() + .setSourceFile(execPathEndingWith(mergeAction.getInputs(), "bin")) + .setBundlePath("bin") + .setExternalFileAttribute(BundleableFile.EXECUTABLE_EXTERNAL_FILE_ATTRIBUTE) + .build()) + .setBundleRoot("Payload/bin.app") + .setBundleInfoPlistFile( + execPathEndingWith(mergeAction.getInputs(), "bin-MergedInfo.plist")) + .setOutFile(execPathEndingWith(mergeAction.getOutputs(), "bin.unprocessed.ipa")) + .setMinimumOsVersion(DEFAULT_IOS_SDK_VERSION.toString()) + .setSdkVersion(DEFAULT_IOS_SDK_VERSION.toString()) + .setPlatform("IOS_SIMULATOR") + .setFallbackBundleIdentifier("example.bin") + .build()); + } + + @Test + public void testCreate_mergeBundleAction() throws Exception { + createLibraryTargetWriter("//lib1:lib1") + .setAndCreateFiles("srcs", "a.m", "b.m", "private.h") + .setAndCreateFiles("hdrs", "hdr.h") + .write(); + createLibraryTargetWriter("//lib2:lib2") + .setAndCreateFiles("srcs", "a.m", "b.m", "private.h") + .setAndCreateFiles("hdrs", "hdr.h") + .write(); + createBinaryTargetWriter("//bin:bin") + .setAndCreateFiles("srcs", "a.m") + .setList("deps", "//lib1:lib1", "//lib2:lib2") + .set("infoplist", "'bin-Info.plist'") + .write(); + + SpawnAction action = bundleMergeAction("//bin:bin"); + assertThat(Artifact.toRootRelativePaths(action.getInputs())) + .containsExactly( + MOCK_BUNDLEMERGE_PATH, + "bin/bin_lipobin", + "bin/bin.ipa-control", + "bin/bin-MergedInfo.plist"); + assertThat(Artifact.toRootRelativePaths(action.getOutputs())) + .containsExactly("bin/bin.unprocessed.ipa"); + assertNotRequiresDarwin(action); + assertThat(action.getEnvironment()).isEmpty(); + assertThat(action.getArguments()) + .containsExactly( + MOCK_BUNDLEMERGE_PATH, execPathEndingWith(action.getInputs(), "bin.ipa-control")) + .inOrder(); + } + + @Test + public void testCheckPrimaryBundleIdInMergedPlist() throws Exception { + checkPrimaryBundleIdInMergedPlist(RULE_TYPE); + } + + @Test + public void testCheckFallbackBundleIdInMergedPlist() throws Exception { + checkFallbackBundleIdInMergedPlist(RULE_TYPE); + } + + @Test + public void testCreate_errorForNoSourceOrDep() throws Exception { + scratch.file("x/Foo.plist"); + checkError("x", "x", REQUIRES_AT_LEAST_ONE_LIBRARY_OR_SOURCE_FILE, + "objc_binary(name='x')"); + } + + @Test + public void testCompileWithDotMFileInHeaders() throws Exception { + checkCompileWithDotMFileInHeaders(RULE_TYPE); + } + + @Test + public void testCreate_NoDebugSymbolActionWithoutAppleFlag() throws Exception { + checkNoDebugSymbolFileWithoutAppleFlag(RULE_TYPE); + } + + @Test + public void testErrorForLaunchImageGivenWithNoAssetCatalog() throws Exception { + checkAssetCatalogAttributeError(RULE_TYPE, LAUNCH_IMAGE_ATTR); + } + + @Test + public void testErrorForAppIconGivenWithNoAssetCatalog() throws Exception { + checkAssetCatalogAttributeError(RULE_TYPE, APP_ICON_ATTR); + } + + @Test + public void testCollectsAssetCatalogsTransitively() throws Exception { + scratch.file("lib/ac.xcassets/foo"); + scratch.file("lib/ac.xcassets/bar"); + createLibraryTargetWriter("//lib:lib") + .setAndCreateFiles("srcs", "a.m", "b.m", "private.h") + .set("asset_catalogs", "glob(['ac.xcassets/**'])") + .write(); + scratch.file("bin/ac.xcassets/baz"); + scratch.file("bin/ac.xcassets/42"); + createBinaryTargetWriter("//bin:bin") + .setAndCreateFiles("srcs", "src.m") + .setList("deps", "//lib:lib") + .set("asset_catalogs", "glob(['ac.xcassets/**'])") + .write(); + + // Test that the actoolzip Action has arguments and inputs obtained from dependencies. + SpawnAction actoolZipAction = actoolZipActionForIpa("//bin:bin"); + assertThat(Artifact.toExecPaths(actoolZipAction.getInputs())).containsExactly( + "lib/ac.xcassets/foo", "lib/ac.xcassets/bar", "bin/ac.xcassets/baz", "bin/ac.xcassets/42", + MOCK_ACTOOLWRAPPER_PATH); + assertContainsSublist(actoolZipAction.getArguments(), + ImmutableList.of("lib/ac.xcassets", "bin/ac.xcassets")); + } + + @Test + public void testCcDependencyLinkoptsArePropagatedToLinkAction() throws Exception { + useConfiguration("--experimental_disable_go", "--experimental_disable_jvm", "--cpu=ios_i386", + "--crosstool_top=//tools/osx/crosstool:crosstool"); + + scratch.file("bin/BUILD", + "cc_library(", + " name = 'cclib1',", + " srcs = ['dep1.c'],", + " linkopts = ['-framework F1', '-framework F2', '-Wl,--other-opt'],", + ")", + "cc_library(", + " name = 'cclib2',", + " srcs = ['dep2.c'],", + " linkopts = ['-another-opt', '-framework F2'],", + " deps = ['cclib1'],", + ")", + "cc_library(", + " name = 'cclib3',", + " srcs = ['dep2.c'],", + " linkopts = ['-one-more-opt', '-framework UIKit'],", + " deps = ['cclib1'],", + ")", + "objc_binary(", + " name = 'bin',", + " srcs = ['bin.m'],", + " deps = [':cclib2', ':cclib3'],", + ")"); + + // Frameworks from the CROSSTOOL "apply_implicit_frameworks" feature should be present. + assertThat(Joiner.on(" ").join(linkAction("//bin").getArguments())) + .contains("-framework Foundation -framework UIKit"); + // Frameworks included in linkopts by the user should get placed together with no duplicates. + // (They may duplicate the ones inserted by the CROSSTOOL feature, but we don't test that here.) + assertThat(Joiner.on(" ").join(linkAction("//bin").getArguments())) + .contains("-framework F2 -framework F1"); + // Linkopts should also be grouped together. + assertThat(Joiner.on(" ").join(linkAction("//bin").getArguments())) + .contains("-another-opt -Wl,--other-opt -one-more-opt"); + } + + @Test + public void testAlwaysLinkCcDependenciesAreForceLoaded() throws Exception { + useConfiguration("--experimental_disable_go", "--experimental_disable_jvm", "--cpu=ios_i386", + "--crosstool_top=//tools/osx/crosstool:crosstool"); + + scratch.file("bin/BUILD", + "cc_library(", + " name = 'cclib1',", + " srcs = ['dep1.c'],", + " alwayslink = 1,", + ")", + "cc_library(", + " name = 'cclib2',", + " srcs = ['dep2.c'],", + " deps = [':cclib1'],", + ")", + "objc_binary(", + " name = 'bin',", + " srcs = ['bin.m'],", + " deps = [':cclib2'],", + ")"); + + // cclib1 is force loaded. + assertThat(Joiner.on(" ").join(linkAction("//bin").getArguments())) + .containsMatch(Pattern.compile(" -force_load [^\\s]+/libcclib1.lo\\b")); + } + + @Test + public void testSpecifyAppIconAndLaunchImageUsingXcassetsOfDependency() throws Exception { + checkSpecifyAppIconAndLaunchImageUsingXcassetsOfDependency(RULE_TYPE); + } + + @Test + public void testCreate_actoolAction() throws Exception { + addTargetWithAssetCatalogs(RULE_TYPE); + checkActoolActionCorrectness(DEFAULT_IOS_SDK_VERSION); + } + + @Test + public void testPassesFamiliesToActool() throws Exception { + checkPassesFamiliesToActool(RULE_TYPE); + } + + @Test + public void testPassesFamiliesToIbtool() throws Exception { + checkPassesFamiliesToIbtool(RULE_TYPE); + } + + @Test + public void testReportsErrorsForInvalidFamiliesAttribute() throws Exception { + checkReportsErrorsForInvalidFamiliesAttribute(RULE_TYPE); + } + + @SuppressWarnings("deprecation") // getMergeWithoutNamePrefixZipList is deprecated + @Test + public void testCreate_mergeActionsWithAssetCatalog() throws Exception { + // TODO(matvore): add this test to IosTestTest.java. + addTargetWithAssetCatalogs(RULE_TYPE); + + Artifact actoolZipOut = getBinArtifact("x.actool.zip", "//x:x"); + assertThat(bundleMergeAction("//x:x").getInputs()).contains(actoolZipOut); + + BundleMergeProtos.Control mergeControl = bundleMergeControl("//x:x"); + assertThat(mergeControl.getMergeZipList()).containsExactly(MergeZip.newBuilder() + .setEntryNamePrefix("Payload/x.app/") + .setSourcePath(actoolZipOut.getExecPathString()) + .build()); + } + + private void addBinAndLibWithRawResources() throws Exception { + addBinAndLibWithResources("resources", "resource1.txt", "ja.lproj/resource2.txt", + "objc_binary"); + } + + private void addBinAndLibWithStrings() throws Exception { + addBinAndLibWithResources("strings", "foo.strings", "ja.lproj/bar.strings", + "objc_binary"); + } + + @Test + public void testCollectsRawResourceFilesTransitively() throws Exception { + addBinAndLibWithRawResources(); + checkCollectsResourceFilesTransitively( + "//bin:bin", + ImmutableList.of("lib/resource1.txt", "bin/ja.lproj/resource2.txt"), + ImmutableList.of("lib/resource1.txt"), + ImmutableSetMultimap.<String, Multiset<String>>of( + "bin_bin", + ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt"), + "bin_static_lib_bin", + ImmutableMultiset.of("bin/ja.lproj/resource2.txt", "lib/resource1.txt"), + "lib_lib", + ImmutableMultiset.of("lib/resource1.txt"))); + } + + @Test + public void testCollectsStringsFilesTransitively() throws Exception { + addBinAndLibWithStrings(); + checkCollectsResourceFilesTransitively( + "//bin:bin", + ImmutableList.of("bin/lib/foo.strings.binary", "bin/bin/ja.lproj/bar.strings.binary"), + ImmutableList.of("lib/foo.strings.binary"), + ImmutableSetMultimap.<String, Multiset<String>>of( + "bin_bin", + ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"), + "bin_static_lib_bin", + ImmutableMultiset.of("bin/ja.lproj/bar.strings", "lib/foo.strings"), + "lib_lib", + ImmutableMultiset.of("lib/foo.strings"))); + } + + @Test + public void testResourceFilesMergedInBundle() throws Exception { + addBinAndLibWithRawResources(); + checkBundleablesAreMerged("//bin:bin", + ImmutableListMultimap.of( + "resource1.txt", "resource1.txt", + "ja.lproj/resource2.txt", "ja.lproj/resource2.txt")); + } + + @Test + public void testStringsFilesMergedInBundle() throws Exception { + addBinAndLibWithStrings(); + checkBundleablesAreMerged("//bin:bin", + ImmutableListMultimap.of( + "foo.strings.binary", "foo.strings", + "ja.lproj/bar.strings.binary", "ja.lproj/bar.strings")); + } + + @Test + public void testLinksFrameworksOfSelfAndTransitiveDependencies() throws Exception { + checkLinksFrameworksOfSelfAndTransitiveDependencies(RULE_TYPE); + } + + @Test + public void testLinksWeakFrameworksOfSelfAndTransitiveDependencies() throws Exception { + checkLinksWeakFrameworksOfSelfAndTransitiveDependencies(RULE_TYPE); + } + + @Test + public void testMergesXcdatamodelZips() throws Exception { + checkMergesXcdatamodelZips(RULE_TYPE); + } + + @Test + public void testPlistRequiresDotInName() throws Exception { + checkError("x", "x", + "'//x:Infoplist' does not produce any objc_binary infoplist files (expected .plist)", + "objc_binary(", + " name = 'x',", + " srcs = ['a.m'],", + " infoplist = 'Infoplist'", + ")"); + } + + @Test + public void testLinkIncludeOrder_staticLibsFirst() throws Exception { + checkLinkIncludeOrderStaticLibsFirst(RULE_TYPE); + } + + @Test + public void testLinkIncludeOrder_frameworksAndSystemLibsFirst() throws Exception { + checkLinkIncludeOrderFrameworksAndSystemLibsFirst(RULE_TYPE); + } + + @Test + public void testLinksDylibsTransitively() throws Exception { + checkLinksDylibsTransitively(RULE_TYPE); + } + + @Test + public void testPopulatesCompilationArtifacts() throws Exception { + checkPopulatesCompilationArtifacts(RULE_TYPE); + } + + @Test + public void testArchivesPrecompiledObjectFiles() throws Exception { + checkArchivesPrecompiledObjectFiles(RULE_TYPE); + } + + @Test + public void testPopulatesBundling() throws Exception { + checkPopulatesBundling(RULE_TYPE); + } + + @Test + public void testRegistersStoryboardCompilationActions() throws Exception { + checkRegistersStoryboardCompileActions(RULE_TYPE, "iphone"); + } + + @Test + public void testSwiftStdlibActions() throws Exception { + checkRegisterSwiftStdlibActions(RULE_TYPE, "iphonesimulator"); + } + + @Test + public void testSwiftStdlibActionsWithToolchain() throws Exception { + useConfiguration("--xcode_toolchain=test_toolchain"); + checkRegisterSwiftStdlibActions(RULE_TYPE, "iphonesimulator", "test_toolchain"); + } + + @Test + public void testRegistersSwiftSupportActions() throws Exception { + checkRegisterSwiftSupportActions(RULE_TYPE, "iphonesimulator"); + } + + @Test + public void testRegistersSwiftSupportActionsWithToolchain() throws Exception { + useConfiguration("--xcode_toolchain=test_toolchain"); + checkRegisterSwiftSupportActions(RULE_TYPE, "iphonesimulator", "test_toolchain"); + } + + @Test + public void testErrorsWrongFileTypeForSrcsWhenCompiling() throws Exception { + checkErrorsWrongFileTypeForSrcsWhenCompiling(RULE_TYPE); + } + + @Test + public void testObjcCopts() throws Exception { + checkObjcCopts(RULE_TYPE); + } + + @Test + public void testObjcCopts_argumentOrdering() throws Exception { + checkObjcCopts_argumentOrdering(RULE_TYPE); + } + + @Test + public void testMergesActoolPartialInfoplist() throws Exception { + checkMergesPartialInfoplists(RULE_TYPE); + } + + @Test + public void checkDefinesFromCcLibraryDep() throws Exception { + checkDefinesFromCcLibraryDep(RULE_TYPE); + } + + @Test + public void testCompileXibActions() throws Exception { + checkCompileXibActions(RULE_TYPE); + } + + @Test + public void testNibZipsMergedIntoBundle() throws Exception { + checkNibZipsMergedIntoBundle(RULE_TYPE); + } + + @Test + public void testAllowVariousNonBlacklistedTypesInHeaders() throws Exception { + checkAllowVariousNonBlacklistedTypesInHeaders(RULE_TYPE); + } + + @Test + public void testWarningForBlacklistedTypesInHeaders() throws Exception { + checkWarningForBlacklistedTypesInHeaders(RULE_TYPE); + } + + @Test + public void testCppSourceCompilesWithCppFlags() throws Exception { + checkCppSourceCompilesWithCppFlags(RULE_TYPE); + } + + @Test + public void testPassesFallbackBundleIdToBundleMerging() throws Exception { + checkBundleIdPassedAsFallbackId(RULE_TYPE); + } + + @Test + public void testPassesPrimaryBundleIdToBundleMerging() throws Exception { + checkBundleIdPassedAsPrimaryId(RULE_TYPE); + } + + @Test + public void testNestedBundleIdIsNotAffectedByParent() throws Exception { + scratch.file("bndl/BUILD", + "objc_bundle_library(", + " name = 'bndl',", + ")"); + + createLibraryTargetWriter("//lib:lib") + .setAndCreateFiles("hdrs", "lib.h") + .setList("bundles", "//bndl:bndl") + .write(); + + createBinaryTargetWriter("//bin:bin") + .setAndCreateFiles("srcs", "a.m") + .setList("deps", "//lib:lib") + .set("bundle_id", "'com.main.bundle'") + .write(); + + BundleMergeProtos.Control control = bundleMergeControl("//bin:bin"); + + assertThat(control.getPrimaryBundleIdentifier()).isEqualTo("com.main.bundle"); + // The nested bndl should not get its parent's bundle_id + assertThat(control.getNestedBundleList().get(0).getPrimaryBundleIdentifier()) + .isNotEqualTo("com.main.bundle"); + } + + @Test + public void testAutomaticPlistEntries() throws Exception { + checkAutomaticPlistEntries(RULE_TYPE); + } + + @Test + public void testBundleMergeInputContainsPlMergeOutput() throws Exception { + checkBundleMergeInputContainsPlMergeOutput(RULE_TYPE); + } + + @Test + public void testMultipleInfoPlists() throws Exception { + checkMultipleInfoPlists(RULE_TYPE); + } + + @Test + public void testInfoplistAndInfoplistsTogether() throws Exception { + checkInfoplistAndInfoplistsTogether(RULE_TYPE); + } + + @Test + public void testLinkOpts() throws Exception { + checkLinkopts(RULE_TYPE); + } + + @Test + public void testProtoBundlingAndLinking() throws Exception { + checkProtoBundlingAndLinking(RULE_TYPE); + } + + @Test + public void testProtoBundlingWithTargetsWithNoDeps() throws Exception { + checkProtoBundlingWithTargetsWithNoDeps(RULE_TYPE); + } + + @Test + public void testCanUseCrosstool() throws Exception { + checkLinkingRuleCanUseCrosstool(RULE_TYPE); + } + + @Test + public void testBinaryStrippings() throws Exception { + checkBinaryStripAction(RULE_TYPE); + } + + @Test + public void testAppleSdkVersionEnv() throws Exception { + addMockBinAndLibs(ImmutableList.of("a.m")); + CommandAction action = linkAction("//bin:bin"); + + assertAppleSdkVersionEnv(action); + } + + @Test + public void testNonDefaultAppleSdkVersionEnv() throws Exception { + useConfiguration("--ios_sdk_version=8.1"); + + addMockBinAndLibs(ImmutableList.of("a.m")); + CommandAction action = linkAction("//bin:bin"); + + assertAppleSdkVersionEnv(action, "8.1"); + } + + @Test + public void testAppleSdkDefaultPlatformEnv() throws Exception { + addMockBinAndLibs(ImmutableList.of("a.m")); + CommandAction action = linkAction("//bin:bin"); + + assertAppleSdkPlatformEnv(action, "iPhoneSimulator"); + } + + @Test + public void testAppleSdkDevicePlatformEnv() throws Exception { + useConfiguration("--cpu=ios_arm64"); + + addMockBinAndLibs(ImmutableList.of("a.m")); + CommandAction action = linkAction("//bin:bin"); + + assertAppleSdkPlatformEnv(action, "iPhoneOS"); + } + + @Test + public void testMergeBundleActionsWithNestedBundle() throws Exception { + checkMergeBundleActionsWithNestedBundle(RULE_TYPE); + } + + @Test + public void testIncludesStoryboardOutputZipsAsMergeZips() throws Exception { + checkIncludesStoryboardOutputZipsAsMergeZips(RULE_TYPE); + } + + @Test + public void testCompilationActionsForDebug() throws Exception { + checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG, CodeCoverageMode.NONE); + } + + @Test + public void testClangCoptsForDebugModeWithoutGlib() throws Exception { + checkClangCoptsForDebugModeWithoutGlib(RULE_TYPE); + } + + @Test + public void testCompilationActionsForOptimized() throws Exception { + checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT, CodeCoverageMode.NONE); + } + + @Test + public void testCcDependency() throws Exception { + checkCcDependency(RULE_TYPE); + } + + @Test + public void testLinkActionCorrect() throws Exception { + checkLinkActionCorrect(RULE_TYPE, new ExtraLinkArgs()); + } + + @Test + public void testFrameworkDepLinkFlags() throws Exception { + checkFrameworkDepLinkFlags(RULE_TYPE, new ExtraLinkArgs()); + } + + @Test + public void testLinkActionsWithEmbeddedBitcode() throws Exception { + useConfiguration("--xcode_version=7.1", "--apple_bitcode=embedded", "--ios_multi_cpus=arm64"); + createBinaryTargetWriter("//objc:bin").setAndCreateFiles("srcs", "a.m").write(); + + CommandAction linkAction = linkAction("//objc:bin"); + String commandLine = Joiner.on(" ").join(linkAction.getArguments()); + + assertThat(commandLine).contains("-fembed-bitcode"); + assertThat(commandLine).contains("-Xlinker -bitcode_verify"); + assertThat(commandLine).contains("-Xlinker -bitcode_hide_symbols"); + } + + @Test + public void testLinkActionsWithEmbeddedBitcodeMarkers() throws Exception { + useConfiguration( + "--xcode_version=7.1", "--apple_bitcode=embedded_markers", "--ios_multi_cpus=arm64"); + createBinaryTargetWriter("//objc:bin").setAndCreateFiles("srcs", "a.m").write(); + + CommandAction linkAction = linkAction("//objc:bin"); + + assertThat(Joiner.on(" ").join(linkAction.getArguments())).contains("-fembed-bitcode-marker"); + } + + @Test + public void testCompilationActionsForDebugInGcovCoverage() throws Exception { + checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG, + CodeCoverageMode.GCOV); + } + + @Test + public void testCompilationActionsForDebugInLlvmCovCoverage() throws Exception { + checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.DBG, + CodeCoverageMode.LLVMCOV); + } + + @Test + public void testCompilationActionsForOptimizedInGcovCoverage() throws Exception { + checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT, + CodeCoverageMode.GCOV); + } + + @Test + public void testCompilationActionsForOptimizedInLlvmCovCoverage() throws Exception { + checkClangCoptsForCompilationMode(RULE_TYPE, CompilationMode.OPT, + CodeCoverageMode.LLVMCOV); + } + + @Test + public void testXcodeVersionEnv() throws Exception { + useConfiguration("--xcode_version=5.8"); + + addMockBinAndLibs(ImmutableList.of("a.m")); + CommandAction action = linkAction("//bin:bin"); + + assertXcodeVersionEnv(action, "5.8"); + } + + @Test + public void testCreate_debugSymbolActionWithAppleFlag() throws Exception { + useConfiguration("--apple_generate_dsym"); + RULE_TYPE.scratchTarget(scratch, "srcs", "['a.m']"); + ConfiguredTarget target = getConfiguredTarget("//x:x"); + + Artifact artifact = getBinArtifact("x.app.dSYM.temp.zip", target); + String execPath = artifact.getExecPath().getParentDirectory().toString(); + CommandAction linkAction = (CommandAction) getGeneratingAction(artifact); + assertThat(linkAction.getArguments()).containsAllOf( + "DSYM_HINT_LINKED_BINARY=" + execPath + "/x_bin", + "DSYM_HINT_DSYM_PATH=" + execPath + "/x.app.dSYM.temp", + "DSYM_HINT_DSYM_BUNDLE_ZIP=" + artifact.getExecPathString()); + + Artifact plistArtifact = getBinArtifact("x.app.dSYM/Contents/Info.plist", target); + Artifact debugSymbolArtifact = + getBinArtifact("x.app.dSYM/Contents/Resources/DWARF/x_bin", target); + SpawnAction plistAction = (SpawnAction) getGeneratingAction(plistArtifact); + SpawnAction debugSymbolAction = (SpawnAction) getGeneratingAction(debugSymbolArtifact); + assertThat(debugSymbolAction).isEqualTo(plistAction); + + String dsymUnzipActionArg = + "unzip -p " + + execPath + + "/x.app.dSYM.temp.zip" + + " Contents/Info.plist > " + + plistArtifact.getExecPathString() + + " && unzip -p " + + execPath + + "/x.app.dSYM.temp.zip" + + " Contents/Resources/DWARF/x_bin > " + + debugSymbolArtifact.getExecPathString(); + assertThat(plistAction.getArguments()).contains(dsymUnzipActionArg); + } + + @Test + public void testTargetHasDebugSymbols() throws Exception { + checkTargetHasDebugSymbols(RULE_TYPE); + } + + @Test + public void testFilesToCompileOutputGroup() throws Exception { + checkFilesToCompileOutputGroup(RULE_TYPE); + } +} |