aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/test
diff options
context:
space:
mode:
authorGravatar cpeyser <cpeyser@google.com>2017-07-19 00:19:31 +0200
committerGravatar Klaus Aehlig <aehlig@google.com>2017-07-19 10:22:19 +0200
commit64a0f5664720c2a067483f2ee77caecf17aaca3c (patch)
treea6e01fde6b621994d173d03b53a7fb2efb72a085 /src/test
parentf9a0147f436d99c088ed81a1c964841f6e03fdaf (diff)
Open source j2objc tests.
PiperOrigin-RevId: 162411695
Diffstat (limited to 'src/test')
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java746
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryTest.java101
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/J2ObjcSourceTest.java76
-rw-r--r--src/test/java/com/google/devtools/build/lib/rules/objc/LegacyBazelJ2ObjcLibraryTest.java261
4 files changed, 1184 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
new file mode 100644
index 0000000000..0a3e2a7068
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/BazelJ2ObjcLibraryTest.java
@@ -0,0 +1,746 @@
+// 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.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.AbstractAction;
+import com.google.devtools.build.lib.actions.ActionExecutionContext;
+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.actions.ParameterFileWriteAction;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.rules.cpp.CppModuleMapAction;
+import com.google.devtools.build.lib.rules.cpp.UmbrellaHeaderAction;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Unit test for Java source file translation into ObjC in {@link
+ * com.google.devtools.build.lib.rules.java.JavaLibrary} and translated file compilation and linking
+ * in {@link ObjcBinary} and {@link J2ObjcLibrary}.
+ */
+@RunWith(JUnit4.class)
+public class BazelJ2ObjcLibraryTest extends J2ObjcLibraryTest {
+ @Test
+ public void testJ2ObjCInformationExportedFromJ2ObjcLibrary() throws Exception {
+ ConfiguredTarget j2objcLibraryTarget = getConfiguredTarget(
+ "//java/com/google/dummy/test:transpile");
+ ObjcProvider provider = j2objcLibraryTarget.getProvider(ObjcProvider.class);
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.LIBRARY))).containsExactly(
+ "third_party/java/j2objc/libjre_core_lib.a",
+ "java/com/google/dummy/test/libtest_j2objc.a");
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.HEADER))).containsExactly(
+ "third_party/java/j2objc/jre_core.h",
+ "java/com/google/dummy/test/_j2objc/test/java/com/google/dummy/test/test.h");
+
+ String execPath = j2objcLibraryTarget.getConfiguration().getBinDirectory(RepositoryName.MAIN)
+ .getExecPath() + "/";
+ assertThat(PathFragment.safePathStrings(provider.get(ObjcProvider.INCLUDE)))
+ .containsExactly(execPath + "java/com/google/dummy/test/_j2objc/test");
+ }
+
+ @Test
+ public void testJ2ObjCInformationExportedWithGeneratedJavaSources() throws Exception {
+ scratch.file("java/com/google/test/in.txt");
+ scratch.file("java/com/google/test/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "genrule(",
+ " name = 'dummy_gen',",
+ " srcs = ['in.txt'],",
+ " outs = ['test.java'],",
+ " cmd = 'dummy')",
+ "",
+ "java_library(",
+ " name = 'test',",
+ " srcs = [':test.java'])",
+ "",
+ "j2objc_library(",
+ " name = 'transpile',",
+ " deps = ['test'])");
+
+ ConfiguredTarget target = getConfiguredTarget("//java/com/google/test:transpile");
+ ObjcProvider provider = target.getProvider(ObjcProvider.class);
+ String genfilesFragment = target.getConfiguration().getGenfilesFragment().toString();
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.LIBRARY))).containsExactly(
+ "third_party/java/j2objc/libjre_core_lib.a",
+ "java/com/google/test/libtest_j2objc.a");
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.HEADER))).containsExactly(
+ "third_party/java/j2objc/jre_core.h",
+ "java/com/google/test/_j2objc/test/" + genfilesFragment + "/java/com/google/test/test.h");
+
+ String execPath = target.getConfiguration().getBinDirectory(RepositoryName.MAIN)
+ .getExecPath() + "/";
+ assertThat(PathFragment.safePathStrings(provider.get(ObjcProvider.INCLUDE))).containsExactly(
+ execPath + "java/com/google/test/_j2objc/test/" + genfilesFragment,
+ execPath + "java/com/google/test/_j2objc/test");
+ }
+
+ @Test
+ public void testJ2ObjcProtoRuntimeLibraryAndHeadersExported() throws Exception {
+ scratch.file("java/com/google/dummy/test/proto/test.java");
+ scratch.file("java/com/google/dummy/test/proto/test.proto");
+ scratch.file("java/com/google/dummy/test/proto/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "proto_library(",
+ " name = 'test_proto',",
+ " srcs = ['test.proto'],",
+ " java_api_version = 2,",
+ " j2objc_api_version = 1)",
+ "",
+ "java_library(",
+ " name = 'test',",
+ " srcs = ['test.java'],",
+ " deps = [':test_proto'])",
+ "",
+ "j2objc_library(",
+ " name = 'transpile',",
+ " deps = ['test'])");
+
+ ConfiguredTarget j2objcLibraryTarget = getConfiguredTarget(
+ "//java/com/google/dummy/test/proto:transpile");
+ ObjcProvider provider = j2objcLibraryTarget.getProvider(ObjcProvider.class);
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.LIBRARY))).containsExactly(
+ "third_party/java/j2objc/libjre_core_lib.a",
+ "third_party/java/j2objc/libproto_runtime.a",
+ "java/com/google/dummy/test/proto/libtest_j2objc.a",
+ "java/com/google/dummy/test/proto/libtest_proto_j2objc.a");
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.HEADER))).containsExactly(
+ "third_party/java/j2objc/jre_core.h",
+ "third_party/java/j2objc/runtime.h",
+ "java/com/google/dummy/test/proto/test.j2objc.pb.h",
+ "java/com/google/dummy/test/proto/_j2objc/test/java/com/google/dummy/test/proto/test.h");
+ }
+
+ @Test
+ public void testJ2ObjcHeaderMapExportedInJavaLibrary() throws Exception {
+ scratch.file("java/com/google/transpile/BUILD",
+ "java_library(name = 'dummy',",
+ " srcs = ['dummy.java'])");
+
+ ConfiguredTarget target = getJ2ObjCAspectConfiguredTarget("//java/com/google/transpile:dummy");
+ J2ObjcMappingFileProvider provider = target.getProvider(J2ObjcMappingFileProvider.class);
+
+ assertThat(Iterables.getOnlyElement(provider.getHeaderMappingFiles())
+ .getRootRelativePath().toString()).isEqualTo(
+ "java/com/google/transpile/dummy.mapping.j2objc");
+ }
+
+ @Test
+ public void testDepsJ2ObjcHeaderMapExportedInJavaLibraryWithNoSourceFile() throws Exception {
+ scratch.file("java/com/google/transpile/BUILD",
+ "java_library(name = 'dummy',",
+ " exports = ['//java/com/google/dep:dep'])");
+ scratch.file("java/com/google/dep/BUILD",
+ "java_library(name = 'dep',",
+ " srcs = ['dummy.java'])");
+
+ ConfiguredTarget target = getJ2ObjCAspectConfiguredTarget("//java/com/google/transpile:dummy");
+ J2ObjcMappingFileProvider provider = target.getProvider(J2ObjcMappingFileProvider.class);
+
+ assertThat(Iterables.getOnlyElement(provider.getHeaderMappingFiles())
+ .getRootRelativePath().toString()).isEqualTo(
+ "java/com/google/dep/dep.mapping.j2objc");
+ }
+
+ @Test
+ public void testJ2ObjcProtoClassMappingFilesExportedInJavaLibrary() throws Exception {
+ scratch.file("java/com/google/dummy/test/proto/test.java");
+ scratch.file("java/com/google/dummy/test/proto/test.proto");
+ scratch.file("java/com/google/dummy/test/proto/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "proto_library(",
+ " name = 'test_proto',",
+ " srcs = ['test.proto'],",
+ " java_api_version = 2,",
+ " j2objc_api_version = 1)",
+ "",
+ "java_library(",
+ " name = 'test',",
+ " srcs = ['test.java'],",
+ " deps = [':test_proto'])");
+
+ ConfiguredTarget target = getJ2ObjCAspectConfiguredTarget(
+ "//java/com/google/dummy/test/proto:test");
+ ConfiguredTarget proto =
+ getConfiguredTarget(
+ "//java/com/google/dummy/test/proto:test", getAppleCrosstoolConfiguration());
+ J2ObjcMappingFileProvider provider = target.getProvider(J2ObjcMappingFileProvider.class);
+ Artifact classMappingFile = getGenfilesArtifact("test.clsmap.properties", proto);
+
+ assertThat(provider.getClassMappingFiles()).containsExactly(classMappingFile);
+ }
+
+ @Test
+ public void testJavaProtoLibraryWithProtoLibrary() throws Exception {
+ scratch.file("x/BUILD",
+ "proto_library(",
+ " name = 'test_proto',",
+ " srcs = ['test.proto'],",
+ " java_api_version = 2,",
+ " j2objc_api_version = 1)",
+ "",
+ "java_proto_library(",
+ " name = 'test_java_proto',",
+ " deps = [':test_proto'])",
+ "",
+ "java_library(",
+ " name = 'test',",
+ " srcs = ['test.java'],",
+ " deps = [':test_java_proto'])");
+
+ ConfiguredTarget target = getJ2ObjCAspectConfiguredTarget("//x:test");
+ ConfiguredTarget test = getConfiguredTarget("//x:test_proto", getAppleCrosstoolConfiguration());
+ J2ObjcMappingFileProvider provider = target.getProvider(J2ObjcMappingFileProvider.class);
+ Artifact classMappingFile = getGenfilesArtifact("test.clsmap.properties", test);
+ assertThat(provider.getClassMappingFiles()).containsExactly(classMappingFile);
+
+ ObjcProvider objcProvider = target.getProvider(ObjcProvider.class);
+ Artifact headerFile = getGenfilesArtifact("test.j2objc.pb.h", test);
+ Artifact sourceFile = getGenfilesArtifact("test.j2objc.pb.m", test);
+ assertThat(objcProvider.get(ObjcProvider.HEADER)).contains(headerFile);
+ assertThat(objcProvider.get(ObjcProvider.SOURCE)).contains(sourceFile);
+ }
+
+ @Test
+ public void testJ2ObjcInfoExportedInJavaImport() throws Exception {
+ scratch.file("java/com/google/transpile/BUILD",
+ "java_import(name = 'dummy',",
+ " jars = ['dummy.jar'],",
+ " srcjar = 'dummy.srcjar',",
+ ")");
+
+ ConfiguredTarget target = getJ2ObjCAspectConfiguredTarget("//java/com/google/transpile:dummy");
+ J2ObjcMappingFileProvider provider = target.getProvider(J2ObjcMappingFileProvider.class);
+
+ assertThat(Iterables.getOnlyElement(provider.getHeaderMappingFiles())
+ .getRootRelativePath().toString()).isEqualTo(
+ "java/com/google/transpile/dummy.mapping.j2objc");
+ assertThat(provider.getClassMappingFiles()).isEmpty();
+ }
+
+ protected void checkObjcArchiveAndLinkActions(
+ String targetLabel,
+ String archiveFileName,
+ String objFileName,
+ Iterable<String> compilationInputExecPaths)
+ throws Exception {
+ String labelName = Label.parseAbsolute(targetLabel).getName();
+ CommandAction linkAction =
+ (CommandAction)
+ getGeneratingAction(
+ getBinArtifact(
+ String.format("%s_bin", labelName), getConfiguredTarget(targetLabel)));
+
+ checkObjcCompileActions(
+ getFirstArtifactEndingWith(linkAction.getInputs(), archiveFileName),
+ objFileName, compilationInputExecPaths);
+ }
+
+ @Test
+ public void testMissingEntryClassesError() throws Exception {
+ useConfiguration("--j2objc_dead_code_removal");
+ checkError("java/com/google/dummy", "transpile", J2ObjcLibrary.NO_ENTRY_CLASS_ERROR_MSG,
+ "j2objc_library(name = 'transpile', deps = ['//java/com/google/dummy/test:test'])");
+ }
+
+ @Test
+ public void testNoJ2ObjcDeadCodeRemovalActionWithoutOptFlag() throws Exception {
+ useConfiguration("--noj2objc_dead_code_removal");
+ addSimpleJ2ObjcLibraryWithEntryClasses();
+ addSimpleBinaryTarget("//java/com/google/app/test:transpile");
+
+ Artifact expectedPrunedSource = getBinArtifact(
+ "_j2objc_pruned/app/java/com/google/app/test/_j2objc/test/"
+ + "java/com/google/app/test/test_pruned.m", getConfiguredTarget("//app:app"));
+ assertThat(getGeneratingAction(expectedPrunedSource)).isNull();
+ }
+
+ @Test
+ public void testExplicitJreDeps() throws Exception {
+ ConfiguredTarget j2objcLibraryTarget = getConfiguredTarget(
+ "//java/com/google/dummy/test:transpile");
+ ObjcProvider provider = j2objcLibraryTarget.getProvider(ObjcProvider.class);
+ // jre_io_lib and jre_emul_lib should be excluded.
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.LIBRARY))).containsExactly(
+ "third_party/java/j2objc/libjre_core_lib.a",
+ "java/com/google/dummy/test/libtest_j2objc.a");
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.HEADER))).containsExactly(
+ "third_party/java/j2objc/jre_core.h",
+ "java/com/google/dummy/test/_j2objc/test/java/com/google/dummy/test/test.h");
+ }
+
+ @Test
+ public void testTranspilationActionTreeArtifactOutputsFromSourceJar() throws Exception {
+ useConfiguration("--ios_cpu=i386", "--ios_minimum_os=1.0");
+ scratch.file("java/com/google/transpile/dummy.java");
+ scratch.file("java/com/google/transpile/dummyjar.srcjar");
+ scratch.file("java/com/google/transpile/BUILD",
+ "java_library(name = 'dummy',",
+ " srcs = ['dummy.java', 'dummyjar.srcjar'],",
+ ")");
+
+ ConfiguredTarget target = getJ2ObjCAspectConfiguredTarget("//java/com/google/transpile:dummy");
+ ObjcProvider provider = target.getProvider(ObjcProvider.class);
+ Artifact srcJarSources = getFirstArtifactEndingWith(
+ provider.get(ObjcProvider.SOURCE), "source_files");
+ Artifact srcJarHeaders = getFirstArtifactEndingWith(
+ provider.get(ObjcProvider.HEADER), "header_files");
+ assertThat(srcJarSources.getRootRelativePathString())
+ .isEqualTo("java/com/google/transpile/_j2objc/src_jar_files/dummy/source_files");
+ assertThat(srcJarHeaders.getRootRelativePathString())
+ .isEqualTo("java/com/google/transpile/_j2objc/src_jar_files/dummy/header_files");
+ assertThat(srcJarSources.isTreeArtifact()).isTrue();
+ assertThat(srcJarHeaders.isTreeArtifact()).isTrue();
+ }
+
+ @Test
+ public void testGeneratedTreeArtifactFromGenJar() throws Exception {
+ useConfiguration("--ios_cpu=i386", "--ios_minimum_os=1.0");
+ addSimpleJ2ObjcLibraryWithJavaPlugin();
+ ConfiguredTarget j2objcLibraryTarget =
+ getConfiguredTarget("//java/com/google/app/test:transpile");
+ ObjcProvider provider = j2objcLibraryTarget.getProvider(ObjcProvider.class);
+ Artifact headers =
+ getFirstArtifactEndingWith(provider.get(ObjcProvider.HEADER), "header_files");
+ Artifact sources =
+ getFirstArtifactEndingWith(provider.get(ObjcProvider.SOURCE), "source_files");
+ assertThat(headers.isTreeArtifact()).isTrue();
+ assertThat(sources.isTreeArtifact()).isTrue();
+
+ SpawnAction j2objcAction = (SpawnAction) getGeneratingAction(headers);
+ assertThat(j2objcAction.getOutputs()).containsAllOf(headers, sources);
+
+ Artifact paramFile = getFirstArtifactEndingWith(j2objcAction.getInputs(), ".param.j2objc");
+ ParameterFileWriteAction paramFileAction =
+ (ParameterFileWriteAction) getGeneratingAction(paramFile);
+ assertContainsSublist(
+ ImmutableList.copyOf(paramFileAction.getContents()),
+ ImmutableList.of(
+ "--output_gen_source_dir",
+ sources.getExecPathString(),
+ "--output_gen_header_dir",
+ headers.getExecPathString()));
+ }
+
+ @Test
+ public void testCrosstoolCompilationSupport() throws Exception {
+ MockObjcSupport.createCrosstoolPackage(mockToolsConfig);
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all");
+ addSimpleBinaryTarget("//java/com/google/dummy/test:transpile");
+ assertThat(getConfiguredTarget("//app:app")).isNotNull();
+ }
+
+ @Test
+ public void testProtoCrosstoolCompilationSupport() throws Exception {
+ MockObjcSupport.createCrosstoolPackage(mockToolsConfig);
+ useConfiguration(
+ "--crosstool_top=" + MockObjcSupport.DEFAULT_OSX_CROSSTOOL,
+ "--experimental_objc_crosstool=all");
+ scratch.file("x/test.java");
+ scratch.file("x/test.proto");
+ scratch.file("x/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "proto_library(",
+ " name = 'test_proto',",
+ " srcs = ['test.proto'],",
+ " cc_api_version = 2,",
+ " java_api_version = 2,",
+ " j2objc_api_version = 1)",
+ "",
+ "java_library(",
+ " name = 'test',",
+ " srcs = ['test.java'],",
+ " deps = [':test_proto'])",
+ "",
+ "j2objc_library(",
+ " name = 'transpile',",
+ " deps = ['test'])");
+ addSimpleBinaryTarget("//x:transpile");
+ assertThat(getConfiguredTarget("//app:app")).isNotNull();
+ }
+
+ @Test
+ public void testJ2ObjcHeaderMappingAction() throws Exception {
+ scratch.file("java/com/google/transpile/BUILD",
+ "java_library(name = 'lib1',",
+ " srcs = ['libOne.java', 'jar.srcjar'],",
+ " deps = [':lib2']",
+ ")",
+ "",
+ "java_library(name = 'lib2',",
+ " srcs = ['libTwo.java'],",
+ ")");
+
+ ConfiguredTarget target = getJ2ObjCAspectConfiguredTarget(
+ "//java/com/google/transpile:lib1");
+ J2ObjcMappingFileProvider mappingFileProvider =
+ target.getProvider(J2ObjcMappingFileProvider.class);
+ assertThat(Artifact.toRootRelativePaths(mappingFileProvider.getHeaderMappingFiles()))
+ .containsExactly(
+ "java/com/google/transpile/lib1.mapping.j2objc",
+ "java/com/google/transpile/lib2.mapping.j2objc");
+
+ Artifact mappingFile = getFirstArtifactEndingWith(
+ mappingFileProvider.getHeaderMappingFiles(), "lib1.mapping.j2objc");
+ SpawnAction headerMappingAction = (SpawnAction) getGeneratingAction(mappingFile);
+ String execPath = target.getConfiguration().getBinDirectory(RepositoryName.MAIN)
+ .getExecPath() + "/";
+ assertThat(Artifact.toRootRelativePaths(headerMappingAction.getInputs()))
+ .containsAllOf(
+ "java/com/google/transpile/libOne.java", "java/com/google/transpile/jar.srcjar");
+ assertThat(headerMappingAction.getArguments())
+ .containsExactly(
+ "tools/j2objc/j2objc_header_map.py",
+ "--source_files",
+ "java/com/google/transpile/libOne.java",
+ "--source_jars",
+ "java/com/google/transpile/jar.srcjar",
+ "--output_mapping_file",
+ execPath + "java/com/google/transpile/lib1.mapping.j2objc")
+ .inOrder();
+ }
+
+ protected void checkObjcCompileActions(
+ Artifact archiveFile, String objFileName, Iterable<String> compilationInputExecPaths)
+ throws Exception {
+ CommandAction compileAction = getObjcCompileAction(archiveFile, objFileName);
+ assertThat(Artifact.toRootRelativePaths(compileAction.getInputs())).containsAllIn(
+ compilationInputExecPaths);
+ }
+
+ protected CommandAction getObjcCompileAction(Artifact archiveFile, String objFileName)
+ throws Exception {
+ CommandAction archiveAction = (CommandAction) getGeneratingAction(archiveFile);
+ CommandAction compileAction =
+ (CommandAction)
+ getGeneratingAction(getFirstArtifactEndingWith(archiveAction.getInputs(), objFileName));
+ return compileAction;
+ }
+
+ protected void addSimpleBinaryTarget(String j2objcLibraryTargetDep) throws Exception {
+ scratch.file("app/app.m");
+ scratch.file("app/Info.plist");
+ scratch.file("app/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "objc_library(",
+ " name = 'lib',",
+ " deps = ['" + j2objcLibraryTargetDep + "'])",
+ "",
+ "objc_binary(",
+ " name = 'app',",
+ " srcs = ['app.m'],",
+ " deps = [':lib'],",
+ ")");
+
+ }
+
+ protected void addSimpleJ2ObjcLibraryWithEntryClasses() throws Exception {
+ scratch.file("java/com/google/app/test/test.java");
+ scratch.file("java/com/google/app/test/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_library(",
+ " name = 'test',",
+ " srcs = ['test.java'])",
+ "",
+ "j2objc_library(",
+ " name = 'transpile',",
+ " entry_classes = ['com.google.app.test.test'],",
+ " deps = ['test'])");
+ }
+
+ protected void addSimpleJ2ObjcLibraryWithJavaPlugin() throws Exception {
+ scratch.file("java/com/google/app/test/test.java");
+ scratch.file("java/com/google/app/test/plugin.java");
+ scratch.file(
+ "java/com/google/app/test/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_library(",
+ " name = 'test',",
+ " srcs = ['test.java'],",
+ " plugins = [':plugin'])",
+ "",
+ "java_plugin(",
+ " name = 'plugin',",
+ " processor_class = 'com.google.process.stuff',",
+ " srcs = ['plugin.java'])",
+ "",
+ "j2objc_library(",
+ " name = 'transpile',",
+ " deps = [':test'])");
+ }
+
+ protected Artifact j2objcArchive(String j2objcLibraryTarget, String javaTargetName)
+ throws Exception {
+ ConfiguredTarget target = getConfiguredTarget(j2objcLibraryTarget);
+ ObjcProvider provider = target.getProvider(ObjcProvider.class);
+ String archiveName = String.format("lib%s_j2objc.a", javaTargetName);
+ return getFirstArtifactEndingWith(provider.get(ObjcProvider.LIBRARY), archiveName);
+ }
+
+ @Test
+ public void testJ2ObjcInformationExportedFromObjcLibrary() throws Exception {
+ scratch.file("app/lib.m");
+ scratch.file(
+ "app/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.m'],",
+ " deps = ['//java/com/google/dummy/test:transpile'])");
+
+ ConfiguredTarget objcTarget = getConfiguredTarget("//app:lib");
+
+ ObjcProvider provider = objcTarget.getProvider(ObjcProvider.class);
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.LIBRARY)))
+ .containsExactly(
+ "third_party/java/j2objc/libjre_core_lib.a",
+ "java/com/google/dummy/test/libtest_j2objc.a",
+ "app/liblib.a");
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.HEADER)))
+ .containsExactly(
+ "third_party/java/j2objc/jre_core.h",
+ "java/com/google/dummy/test/_j2objc/test/java/com/google/dummy/test/test.h");
+
+ String execPath =
+ objcTarget.getConfiguration().getBinDirectory(RepositoryName.MAIN).getExecPath() + "/";
+ assertThat(PathFragment.safePathStrings(provider.get(ObjcProvider.INCLUDE)))
+ .containsExactly(execPath + "java/com/google/dummy/test/_j2objc/test");
+ }
+
+ @Test
+ public void testJ2ObjcInfoExportedInObjcLibraryFromRuntimeDeps() throws Exception {
+ scratch.file("app/lib.m");
+ scratch.file(
+ "app/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "",
+ "java_library(name = 'dummyOne',",
+ " srcs = ['dummyOne.java'])",
+ "java_library(name = 'dummyTwo',",
+ " srcs = ['dummyTwo.java'],",
+ " runtime_deps = [':dummyOne'])",
+ "",
+ "j2objc_library(",
+ " name = 'transpile',",
+ " deps = [':dummyTwo'])",
+ "",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.m'],",
+ " deps = ['//app:transpile'])");
+
+ ConfiguredTarget objcTarget = getConfiguredTarget("//app:lib");
+
+ ObjcProvider provider = objcTarget.getProvider(ObjcProvider.class);
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.LIBRARY)))
+ .containsExactly(
+ "third_party/java/j2objc/libjre_core_lib.a",
+ "app/libdummyOne_j2objc.a",
+ "app/libdummyTwo_j2objc.a",
+ "app/liblib.a");
+ assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.HEADER)))
+ .containsExactly(
+ "third_party/java/j2objc/jre_core.h",
+ "app/_j2objc/dummyOne/app/dummyOne.h",
+ "app/_j2objc/dummyTwo/app/dummyTwo.h");
+
+ String execPath =
+ objcTarget.getConfiguration().getBinDirectory(RepositoryName.MAIN).getExecPath() + "/";
+ assertThat(PathFragment.safePathStrings(provider.get(ObjcProvider.INCLUDE)))
+ .containsExactly(execPath + "app/_j2objc/dummyOne", execPath + "app/_j2objc/dummyTwo");
+ }
+
+ @Test
+ public void testJ2ObjcAppearsInLinkArgs() throws Exception {
+ scratch.file(
+ "java/c/y/BUILD", "java_library(", " name = 'ylib',", " srcs = ['lib.java'],", ")");
+ scratch.file(
+ "x/BUILD",
+ "j2objc_library(",
+ " name = 'j2',",
+ " deps = [ '//java/c/y:ylib' ],",
+ " jre_deps = [ '//third_party/java/j2objc:jre_io_lib' ])",
+ "ios_application(",
+ " name = 'app',",
+ " binary = ':bin',",
+ " infoplist = 'info.plist',",
+ ")",
+ "objc_binary(",
+ " name = 'bin',",
+ " srcs = ['bin.m'],",
+ " deps = [':j2'],",
+ ")",
+ "ios_test(",
+ " name = 'test',",
+ " srcs = ['test.m'],",
+ " deps = [':j2'],",
+ " xctest = 1,",
+ " xctest_app = ':app',",
+ ")");
+
+ CommandAction linkAction = linkAction("//x:test");
+ List<String> linkArgs = normalizeBashArgs(linkAction.getArguments());
+ ConfiguredTarget target = getConfiguredTarget("//x:test");
+ String binDir =
+ target.getConfiguration().getBinDirectory(RepositoryName.MAIN).getExecPathString();
+ Artifact fileList = getFirstArtifactEndingWith(linkAction.getInputs(), "test-linker.objlist");
+ ParameterFileWriteAction filelistWriteAction =
+ (ParameterFileWriteAction) getGeneratingAction(fileList);
+ assertThat(linkArgs).contains(fileList.getExecPathString());
+ assertThat(filelistWriteAction.getContents())
+ .containsAllOf(
+ binDir + "/java/c/y/libylib_j2objc.a",
+ // All jre libraries mus appear after java libraries in the link order.
+ binDir + "/third_party/java/j2objc/libjre_io_lib.a",
+ binDir + "/third_party/java/j2objc/libjre_core_lib.a")
+ .inOrder();
+ }
+
+ @Test
+ public void testArchiveLinkActionWithTreeArtifactFromGenJar() throws Exception {
+ useConfiguration("--ios_cpu=i386", "--ios_minimum_os=1.0");
+ addSimpleJ2ObjcLibraryWithJavaPlugin();
+ Artifact archive = j2objcArchive("//java/com/google/app/test:transpile", "test");
+ CommandAction archiveAction = (CommandAction) getGeneratingAction(archive);
+ Artifact archiveObjList =
+ getFirstArtifactEndingWith(archiveAction.getInputs(), "-archive.objlist");
+ Artifact objectFilesFromGenJar =
+ getFirstArtifactEndingWith(archiveAction.getInputs(), "source_files");
+ Artifact normalObjectFile = getFirstArtifactEndingWith(archiveAction.getInputs(), "test.o");
+
+ ParameterFileWriteAction paramFileAction =
+ (ParameterFileWriteAction) getGeneratingAction(archiveObjList);
+
+ // Test that the archive obj list param file contains the individual object files inside
+ // the object file tree artifact.
+ assertThat(paramFileAction.getContents(DUMMY_ARTIFACT_EXPANDER))
+ .containsExactly(
+ objectFilesFromGenJar.getExecPathString() + "/children1",
+ objectFilesFromGenJar.getExecPathString() + "/children2",
+ normalObjectFile.getExecPathString());
+ }
+
+ @Test
+ public void testJ2ObjCCustomModuleMap() throws Exception {
+ useConfiguration("--experimental_objc_enable_module_maps");
+ scratch.file("java/com/google/transpile/dummy.java");
+ scratch.file("java/com/google/transpile/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_library(name = 'dummy',",
+ " srcs = ['dummy.java'])");
+
+ ConfiguredTarget target = getJ2ObjCAspectConfiguredTarget("//java/com/google/transpile:dummy");
+
+ ObjcProvider provider = target.getProvider(ObjcProvider.class);
+ Artifact moduleMap =
+ getFirstArtifactEndingWith(
+ provider.get(ObjcProvider.MODULE_MAP), "dummy.modulemaps/module.modulemap");
+
+ Artifact umbrellaHeader =
+ getFirstArtifactEndingWith(
+ provider.get(ObjcProvider.UMBRELLA_HEADER), "dummy.modulemaps/umbrella.h");
+
+ CppModuleMapAction moduleMapAction = (CppModuleMapAction) getGeneratingAction(moduleMap);
+ UmbrellaHeaderAction umbrellaHeaderAction =
+ (UmbrellaHeaderAction) getGeneratingAction(umbrellaHeader);
+
+ ActionExecutionContext dummyActionExecutionContext =
+ new ActionExecutionContext(
+ null, null, null, null, ImmutableMap.<String, String>of(), DUMMY_ARTIFACT_EXPANDER);
+ ByteArrayOutputStream moduleMapStream = new ByteArrayOutputStream();
+ ByteArrayOutputStream umbrellaHeaderStream = new ByteArrayOutputStream();
+ moduleMapAction.newDeterministicWriter(dummyActionExecutionContext)
+ .writeOutputFile(moduleMapStream);
+ umbrellaHeaderAction.newDeterministicWriter(dummyActionExecutionContext)
+ .writeOutputFile(umbrellaHeaderStream);
+ String moduleMapContent = moduleMapStream.toString();
+ String umbrellaHeaderContent = umbrellaHeaderStream.toString();
+
+ assertThat(moduleMapContent).contains("umbrella header \"umbrella.h\"");
+ assertThat(umbrellaHeaderContent).contains("/dummy.h");
+ assertThat(umbrellaHeaderContent).contains("#include");
+ }
+
+ @Test
+ public void testModuleMapFromGenJarTreeArtifact() throws Exception {
+ useConfiguration("--ios_cpu=i386", "--ios_minimum_os=1.0");
+ addSimpleJ2ObjcLibraryWithJavaPlugin();
+ ConfiguredTarget j2objcLibraryTarget =
+ getConfiguredTarget("//java/com/google/app/test:transpile");
+ ObjcProvider provider = j2objcLibraryTarget.getProvider(ObjcProvider.class);
+ Artifact moduleMap =
+ getFirstArtifactEndingWith(
+ provider.get(ObjcProvider.MODULE_MAP), "test.modulemaps/module.modulemap");
+ Artifact umbrellaHeader =
+ getFirstArtifactEndingWith(
+ provider.get(ObjcProvider.UMBRELLA_HEADER), "test.modulemaps/umbrella.h");
+
+ CppModuleMapAction moduleMapAction = (CppModuleMapAction) getGeneratingAction(moduleMap);
+ UmbrellaHeaderAction umbrellaHeaderAction =
+ (UmbrellaHeaderAction) getGeneratingAction(umbrellaHeader);
+ Artifact headers =
+ getFirstArtifactEndingWith(provider.get(ObjcProvider.HEADER), "header_files");
+
+ // Test that the module map action contains the header tree artifact as both the public header
+ // and part of the action inputs.
+ assertThat(moduleMapAction.getPublicHeaders()).contains(headers);
+ assertThat(moduleMapAction.getInputs()).contains(headers);
+
+ ActionExecutionContext dummyActionExecutionContext =
+ new ActionExecutionContext(
+ null, null, null, null, ImmutableMap.<String, String>of(), DUMMY_ARTIFACT_EXPANDER);
+
+ ByteArrayOutputStream moduleMapStream = new ByteArrayOutputStream();
+ ByteArrayOutputStream umbrellaHeaderStream = new ByteArrayOutputStream();
+ moduleMapAction
+ .newDeterministicWriter(dummyActionExecutionContext)
+ .writeOutputFile(moduleMapStream);
+ umbrellaHeaderAction
+ .newDeterministicWriter(dummyActionExecutionContext)
+ .writeOutputFile(umbrellaHeaderStream);
+ String moduleMapContent = moduleMapStream.toString();
+ String umbrellaHeaderContent = umbrellaHeaderStream.toString();
+
+ // Test that the module map content contains the individual headers inside the header tree
+ // artifact.
+ assertThat(moduleMapContent).contains("umbrella header \"umbrella.h\"");
+ assertThat(umbrellaHeaderContent).contains(headers.getExecPathString() + "/children1");
+ assertThat(umbrellaHeaderContent).contains(headers.getExecPathString() + "/children2");
+ }
+
+ @Test
+ public void testJ2ObjCFullyLinkAction() throws Exception {
+ AbstractAction linkAction = (AbstractAction) getGeneratingActionForLabel(
+ "//java/com/google/dummy/test:transpile_fully_linked.a");
+ String fullyLinkBinaryPath =
+ Iterables.getOnlyElement(linkAction.getOutputs()).getExecPathString();
+ assertThat(fullyLinkBinaryPath).contains("transpile_fully_linked.a");
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryTest.java
new file mode 100644
index 0000000000..3fff23e56c
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/J2ObjcLibraryTest.java
@@ -0,0 +1,101 @@
+// 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 com.google.devtools.build.lib.actions.ActionInputHelper;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.Artifact.ArtifactExpander;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.packages.util.MockJ2ObjcSupport;
+import com.google.devtools.build.lib.packages.util.MockObjcSupport;
+import com.google.devtools.build.lib.packages.util.MockProtoSupport;
+import java.util.Collection;
+import org.junit.Before;
+
+/**
+ * Setup for unit tests for j2objc transpilation.
+ */
+public class J2ObjcLibraryTest extends ObjcRuleTestCase {
+ protected static final ArtifactExpander DUMMY_ARTIFACT_EXPANDER =
+ new ArtifactExpander() {
+ @Override
+ public void expand(Artifact artifact, Collection<? super Artifact> output) {
+ output.add(ActionInputHelper.treeFileArtifact(artifact, "children1"));
+ output.add(ActionInputHelper.treeFileArtifact(artifact, "children2"));
+ }
+ };
+
+ /**
+ * The configuration to be used for genfiles artifacts.
+ */
+ protected BuildConfiguration getGenfilesConfig() throws InterruptedException {
+ return getAppleCrosstoolConfiguration();
+ }
+
+ /**
+ * Creates and injects a j2objc_library target that depends upon the given label, then returns the
+ * ConfiguredTarget for the label with the aspects added.
+ */
+ protected ConfiguredTarget getJ2ObjCAspectConfiguredTarget(String label) throws Exception {
+ // Blaze exposes no interface to summon aspects ex nihilo.
+ // To get an aspect, you must create a dependent target that requires the aspect.
+ scratch.file("java/com/google/dummy/aspect/BUILD",
+ "j2objc_library(",
+ " name = 'transpile',",
+ " deps = ['" + label + "'],",
+ ")");
+
+ return view.getPrerequisiteConfiguredTargetForTesting(
+ reporter,
+ getConfiguredTarget("//java/com/google/dummy/aspect:transpile"),
+ Label.parseAbsoluteUnchecked(label),
+ masterConfig);
+ }
+
+ @Before
+ public final void setup() throws Exception {
+ scratch.file("java/com/google/dummy/test/test.java");
+ scratch.file("java/com/google/dummy/test/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_library(",
+ " name = 'test',",
+ " srcs = ['test.java'])",
+ "",
+ "j2objc_library(",
+ " name = 'transpile',",
+ " deps = ['test'])");
+ MockObjcSupport.setup(mockToolsConfig);
+ MockObjcSupport.setupIosSimDevice(mockToolsConfig);
+ MockObjcSupport.setupIosTest(mockToolsConfig);
+ MockJ2ObjcSupport.setup(mockToolsConfig);
+ MockProtoSupport.setup(mockToolsConfig);
+ MockObjcSupport.setupObjcProto(mockToolsConfig);
+
+ useConfiguration("--proto_toolchain_for_java=//tools/proto/toolchains:java");
+
+ mockToolsConfig.create(
+ "tools/proto/toolchains/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "proto_lang_toolchain(name = 'java', command_line = 'dont_care')",
+ "proto_lang_toolchain(name='java_stubby1_immutable', command_line = 'dont_care')",
+ "proto_lang_toolchain(name='java_stubby3_immutable', command_line = 'dont_care')",
+ "proto_lang_toolchain(name='java_stubby_compatible13_immutable', "
+ + "command_line = 'dont_care')");
+
+ invalidatePackages();
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/J2ObjcSourceTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/J2ObjcSourceTest.java
new file mode 100644
index 0000000000..3e413f5c6b
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/J2ObjcSourceTest.java
@@ -0,0 +1,76 @@
+// 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 com.google.common.collect.ImmutableList;
+import com.google.common.testing.EqualsTester;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.Root;
+import com.google.devtools.build.lib.cmdline.Label;
+import com.google.devtools.build.lib.testutil.Scratch;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Unit test for {@link J2ObjcSource}.
+ */
+@RunWith(JUnit4.class)
+public class J2ObjcSourceTest {
+ private Root rootDir;
+
+ @Before
+ public final void setRootDir() throws Exception {
+ Scratch scratch = new Scratch();
+ rootDir = Root.asDerivedRoot(scratch.dir("/exec/root"));
+ }
+
+ @Test
+ public void testEqualsAndHashCode() throws Exception {
+ new EqualsTester()
+ .addEqualityGroup(
+ getJ2ObjcSource("//a/b:c", "sourceA", J2ObjcSource.SourceType.JAVA),
+ getJ2ObjcSource("//a/b:c", "sourceA", J2ObjcSource.SourceType.JAVA))
+ .addEqualityGroup(
+ getJ2ObjcSource("//a/b:d", "sourceA", J2ObjcSource.SourceType.JAVA),
+ getJ2ObjcSource("//a/b:d", "sourceA", J2ObjcSource.SourceType.JAVA))
+ .addEqualityGroup(
+ getJ2ObjcSource("//a/b:d", "sourceC", J2ObjcSource.SourceType.JAVA),
+ getJ2ObjcSource("//a/b:d", "sourceC", J2ObjcSource.SourceType.JAVA))
+ .addEqualityGroup(
+ getJ2ObjcSource("//a/b:d", "sourceC", J2ObjcSource.SourceType.PROTO),
+ getJ2ObjcSource("//a/b:d", "sourceC", J2ObjcSource.SourceType.PROTO))
+ .testEquals();
+ }
+
+ private J2ObjcSource getJ2ObjcSource(String label, String fileName,
+ J2ObjcSource.SourceType sourceType) throws Exception {
+ Label ruleLabel = Label.parseAbsolute(label);
+ PathFragment path = ruleLabel.toPathFragment();
+ return new J2ObjcSource(
+ ruleLabel,
+ ImmutableList.of(getArtifactForTest(path.getRelative(fileName + ".m").toString())),
+ ImmutableList.of(getArtifactForTest(path.getRelative(fileName + ".h").toString())),
+ path,
+ sourceType,
+ ImmutableList.of(path));
+ }
+
+ private Artifact getArtifactForTest(String path) throws Exception {
+ return new Artifact(PathFragment.create(path), rootDir);
+ }
+}
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyBazelJ2ObjcLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyBazelJ2ObjcLibraryTest.java
new file mode 100644
index 0000000000..669cac0d4b
--- /dev/null
+++ b/src/test/java/com/google/devtools/build/lib/rules/objc/LegacyBazelJ2ObjcLibraryTest.java
@@ -0,0 +1,261 @@
+// 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.actions.util.ActionsTestUtil.getFirstArtifactEndingWith;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.devtools.build.lib.actions.ActionInputHelper;
+import com.google.devtools.build.lib.actions.Artifact;
+import com.google.devtools.build.lib.actions.Artifact.TreeFileArtifact;
+import com.google.devtools.build.lib.actions.ArtifactOwner;
+import com.google.devtools.build.lib.actions.CommandAction;
+import com.google.devtools.build.lib.analysis.ConfiguredTarget;
+import com.google.devtools.build.lib.analysis.actions.ParameterFileWriteAction;
+import com.google.devtools.build.lib.analysis.actions.SpawnAction;
+import com.google.devtools.build.lib.analysis.actions.SpawnActionTemplate;
+import com.google.devtools.build.lib.analysis.config.BuildConfiguration;
+import com.google.devtools.build.lib.cmdline.RepositoryName;
+import com.google.devtools.build.lib.rules.apple.AppleConfiguration;
+import com.google.devtools.build.lib.rules.apple.AppleToolchain;
+import com.google.devtools.build.lib.rules.objc.ObjcCommandLineOptions.ObjcCrosstoolMode;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Legacy test: These tests test --experimental_objc_crosstool=off. See README in
+ * devtools.build.lib.rules.objc
+ */
+@RunWith(JUnit4.class)
+public class LegacyBazelJ2ObjcLibraryTest extends BazelJ2ObjcLibraryTest {
+ @Override
+ protected ObjcCrosstoolMode getObjcCrosstoolMode() {
+ return ObjcCrosstoolMode.OFF;
+ }
+
+ @Override
+ protected BuildConfiguration getGenfilesConfig() {
+ return targetConfig;
+ }
+
+ @Test
+ public void testObjcCompileAction() throws Exception {
+ Artifact archive = j2objcArchive("//java/com/google/dummy/test:transpile", "test");
+ CommandAction compileAction = getObjcCompileAction(archive, "test.o");
+ assertThat(Artifact.toRootRelativePaths(compileAction.getInputs())).containsExactly(
+ "third_party/java/j2objc/jre_core.h",
+ "java/com/google/dummy/test/_j2objc/test/java/com/google/dummy/test/test.h",
+ "java/com/google/dummy/test/_j2objc/test/java/com/google/dummy/test/test.m",
+ "tools/objc/xcrunwrapper");
+ assertThat(compileAction.getArguments()).containsAllOf("-fno-objc-arc", "-fno-strict-overflow");
+ }
+
+ @Test
+ public void testJ2ObjcSourcesCompilationAndLinking() throws Exception {
+ addSimpleBinaryTarget("//java/com/google/dummy/test:transpile");
+
+ checkObjcArchiveAndLinkActions("//app:app", "libtest_j2objc.a", "test.o", ImmutableList.of(
+ "third_party/java/j2objc/jre_core.h",
+ "java/com/google/dummy/test/_j2objc/test/java/com/google/dummy/test/test.h",
+ "java/com/google/dummy/test/_j2objc/test/java/com/google/dummy/test/test.m"));
+ }
+
+ @Test
+ public void testNestedJ2ObjcLibraryDeps() throws Exception {
+ scratch.file("java/com/google/dummy/dummy.java");
+ scratch.file("java/com/google/dummy/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "java_library(",
+ " name = 'dummy',",
+ " srcs = ['dummy.java'])",
+ "",
+ "j2objc_library(",
+ " name = 'transpile',",
+ " deps = [",
+ " ':dummy',",
+ " '//java/com/google/dummy/test:transpile',",
+ " ])");
+ addSimpleBinaryTarget("//java/com/google/dummy:transpile");
+
+ checkObjcArchiveAndLinkActions("//app:app", "libtest_j2objc.a", "test.o", ImmutableList.of(
+ "third_party/java/j2objc/jre_core.h",
+ "java/com/google/dummy/test/_j2objc/test/java/com/google/dummy/test/test.h",
+ "java/com/google/dummy/test/_j2objc/test/java/com/google/dummy/test/test.m"));
+
+ checkObjcArchiveAndLinkActions("//app:app", "libdummy_j2objc.a", "dummy.o", ImmutableList.of(
+ "third_party/java/j2objc/jre_core.h",
+ "java/com/google/dummy/_j2objc/dummy/java/com/google/dummy/dummy.h",
+ "java/com/google/dummy/_j2objc/dummy/java/com/google/dummy/dummy.m"));
+ }
+
+ @Test
+ public void testJ2ObjcTranspiledHeaderInCompilationAction() throws Exception {
+ scratch.file("app/lib.m");
+ scratch.file("app/BUILD",
+ "package(default_visibility=['//visibility:public'])",
+ "objc_library(",
+ " name = 'lib',",
+ " srcs = ['lib.m'],",
+ " deps = ['//java/com/google/dummy/test:transpile'])");
+
+ checkObjcCompileActions(getBinArtifact("liblib.a", getConfiguredTarget("//app:lib")), "lib.o",
+ ImmutableList.of(
+ "java/com/google/dummy/test/_j2objc/test/java/com/google/dummy/test/test.h"));
+ }
+
+ @Test
+ public void testJ2ObjcDeadCodeRemovalActionWithOptFlag() throws Exception {
+ useConfiguration("--j2objc_dead_code_removal");
+ addSimpleJ2ObjcLibraryWithEntryClasses();
+ addSimpleBinaryTarget("//java/com/google/app/test:transpile");
+
+ ConfiguredTarget appTarget = getConfiguredTarget("//app:app", getAppleCrosstoolConfiguration());
+ Artifact prunedArchive =
+ getBinArtifact(
+ "_j2objc_pruned/app/java/com/google/app/test/libtest_j2objc_pruned.a", appTarget);
+ Artifact paramFile =
+ getBinArtifact("_j2objc_pruned/app/java/com/google/app/test/test.param.j2objc", appTarget);
+
+ ConfiguredTarget javaTarget =
+ getConfiguredTarget("//java/com/google/app/test:test", getAppleCrosstoolConfiguration());
+ Artifact inputArchive = getBinArtifact("libtest_j2objc.a", javaTarget);
+ Artifact headerMappingFile = getBinArtifact("test.mapping.j2objc", javaTarget);
+ Artifact dependencyMappingFile = getBinArtifact("test.dependency_mapping.j2objc", javaTarget);
+ Artifact archiveSourceMappingFile =
+ getBinArtifact("test.archive_source_mapping.j2objc", javaTarget);
+ String execPath =
+ javaTarget.getConfiguration().getBinDirectory(RepositoryName.MAIN).getExecPath() + "/";
+
+ ParameterFileWriteAction paramFileAction =
+ (ParameterFileWriteAction) getGeneratingAction(paramFile);
+ assertContainsSublist(
+ ImmutableList.copyOf(paramFileAction.getContents()),
+ new ImmutableList.Builder<String>()
+ .add("--input_archive")
+ .add(inputArchive.getExecPathString())
+ .add("--output_archive")
+ .add(prunedArchive.getExecPathString())
+ .add("--dummy_archive")
+ .add(execPath + "tools/objc/libdummy_lib.a")
+ .add("--xcrunwrapper")
+ .add("tools/objc/xcrunwrapper")
+ .add("--dependency_mapping_files")
+ .add(dependencyMappingFile.getExecPathString())
+ .add("--header_mapping_files")
+ .add(headerMappingFile.getExecPathString())
+ .add("--archive_source_mapping_files")
+ .add(archiveSourceMappingFile.getExecPathString())
+ .add("--entry_classes")
+ .add("com.google.app.test.test")
+ .build());
+
+ SpawnAction deadCodeRemovalAction = (SpawnAction) getGeneratingAction(prunedArchive);
+ assertContainsSublist(
+ deadCodeRemovalAction.getArguments(),
+ new ImmutableList.Builder<String>()
+ .add("tools/objc/j2objc_dead_code_pruner.py")
+ .add("@" + paramFile.getExecPathString())
+ .build());
+ assertThat(deadCodeRemovalAction.getOutputs()).containsExactly(prunedArchive);
+ }
+
+ @Test
+ public void testCompileActionTemplateFromGenJar() throws Exception {
+ useConfiguration("--cpu=ios_i386", "--ios_minimum_os=1.0");
+ addSimpleJ2ObjcLibraryWithJavaPlugin();
+ Artifact archive = j2objcArchive("//java/com/google/app/test:transpile", "test");
+ CommandAction archiveAction = (CommandAction) getGeneratingAction(archive);
+ Artifact objectFilesFromGenJar =
+ getFirstArtifactEndingWith(archiveAction.getInputs(), "source_files");
+
+ assertThat(objectFilesFromGenJar.isTreeArtifact()).isTrue();
+ assertThat(objectFilesFromGenJar.getRootRelativePathString())
+ .isEqualTo(
+ "java/com/google/app/test/_objs/test/java/com/google/app/test/_j2objc/"
+ + "src_jar_files/test/source_files");
+
+ SpawnActionTemplate actionTemplate =
+ (SpawnActionTemplate) getActionGraph().getGeneratingAction(objectFilesFromGenJar);
+ Artifact sourceFilesFromGenJar =
+ getFirstArtifactEndingWith(actionTemplate.getInputs(), "source_files");
+ Artifact headerFilesFromGenJar =
+ getFirstArtifactEndingWith(actionTemplate.getInputs(), "header_files");
+ assertThat(sourceFilesFromGenJar.getRootRelativePathString())
+ .isEqualTo("java/com/google/app/test/_j2objc/src_jar_files/test/source_files");
+ assertThat(headerFilesFromGenJar.getRootRelativePathString())
+ .isEqualTo("java/com/google/app/test/_j2objc/src_jar_files/test/header_files");
+
+ // The files contained inside the tree artifacts are not known until execution time.
+ // Therefore we need to fake some files inside them to test the action template in this
+ // analysis-time test.
+ TreeFileArtifact oneSourceFileFromGenJar =
+ ActionInputHelper.treeFileArtifact(sourceFilesFromGenJar, "children1.m");
+ TreeFileArtifact oneObjFileFromGenJar =
+ ActionInputHelper.treeFileArtifact(objectFilesFromGenJar, "children1.o");
+ Iterable<SpawnAction> compileActions =
+ actionTemplate.generateActionForInputArtifacts(
+ ImmutableList.of(oneSourceFileFromGenJar), ArtifactOwner.NULL_OWNER);
+ SpawnAction compileAction = Iterables.getOnlyElement(compileActions);
+ ConfiguredTarget j2objcLibraryTarget =
+ getConfiguredTarget("//java/com/google/dummy/test:transpile");
+ String genfilesFragment =
+ j2objcLibraryTarget.getConfiguration().getGenfilesFragment().toString();
+ String binFragment = j2objcLibraryTarget.getConfiguration().getBinFragment().toString();
+ AppleConfiguration appleConfiguration =
+ j2objcLibraryTarget.getConfiguration().getFragment(AppleConfiguration.class);
+
+ assertThat(compileAction.getArguments())
+ .containsExactlyElementsIn(
+ new ImmutableList.Builder<String>()
+ .add(MOCK_XCRUNWRAPPER_PATH)
+ .add("clang")
+ .addAll(AppleToolchain.DEFAULT_WARNINGS.values())
+ .add("-fexceptions")
+ .add("-fasm-blocks")
+ .add("-fobjc-abi-version=2")
+ .add("-fobjc-legacy-dispatch")
+ .add("-DOS_IOS")
+ .add("-mios-simulator-version-min=1.0")
+ .add("-arch", "i386")
+ .add("-isysroot")
+ .add(AppleToolchain.sdkDir())
+ .add("-F")
+ .add(AppleToolchain.sdkDir() + "/Developer/Library/Frameworks")
+ .add("-F")
+ .add(AppleToolchain.platformDeveloperFrameworkDir(appleConfiguration))
+ .add("-O0")
+ .add("-DDEBUG=1")
+ .add("-iquote")
+ .add(".")
+ .add("-iquote")
+ .add(genfilesFragment)
+ .add("-I")
+ .add(binFragment + "/java/com/google/app/test/_j2objc/test")
+ .add("-I")
+ .add(headerFilesFromGenJar.getExecPathString())
+ .add("-fno-strict-overflow")
+ .add("-fno-objc-arc")
+ .add("-c")
+ .add(oneSourceFileFromGenJar.getExecPathString())
+ .add("-o")
+ .add(oneObjFileFromGenJar.getExecPathString())
+ .build())
+ .inOrder();
+ }
+
+}