diff options
author | 2017-07-05 18:03:47 -0400 | |
---|---|---|
committer | 2017-07-06 07:14:09 -0400 | |
commit | 478f763599828f88724ee8b3e59f38539cbdd73d (patch) | |
tree | cb3f07a7e5ac4b8590a5331e494ed4f4f0be85fb /src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryTest.java | |
parent | 6508e317b76ef2f26cff5d95a4a82c13a1913b78 (diff) |
Open source unit tests for the objc rules.
PiperOrigin-RevId: 161010594
Diffstat (limited to 'src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryTest.java')
-rw-r--r-- | src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryTest.java | 854 |
1 files changed, 854 insertions, 0 deletions
diff --git a/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryTest.java b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryTest.java new file mode 100644 index 0000000000..a2689cd8fc --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/rules/objc/ObjcProtoLibraryTest.java @@ -0,0 +1,854 @@ +// 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 com.google.common.base.Joiner; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Ordering; +import com.google.devtools.build.lib.actions.Artifact; +import com.google.devtools.build.lib.actions.CommandAction; +import com.google.devtools.build.lib.actions.util.ActionsTestUtil; +import com.google.devtools.build.lib.analysis.ConfiguredTarget; +import com.google.devtools.build.lib.analysis.actions.FileWriteAction; +import com.google.devtools.build.lib.analysis.actions.SpawnAction; +import com.google.devtools.build.lib.analysis.config.BuildConfiguration; +import com.google.devtools.build.lib.collect.nestedset.NestedSet; +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.cpp.CppModuleMapAction; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Test case for objc_proto_library. */ +@RunWith(JUnit4.class) +public class ObjcProtoLibraryTest extends ObjcRuleTestCase { + + @Before + public final void initializeToolsConfigMock() throws Exception { + MockProtoSupport.setup(mockToolsConfig); + MockObjcSupport.setupObjcProto(mockToolsConfig); + } + + @Before + public final void createFiles() throws Exception { + scratch.file( + "package/BUILD", + "apple_binary(", + " name = 'opl_binary',", + " deps = [':opl_protobuf'],", + " platform_type = 'tvos'", + ")", + "objc_library(", + " name = 'non_strict_lib',", + " deps = [':strict_lib'],", + ")", + "", + "objc_library(", + " name = 'strict_lib',", + " deps = [':opl_protobuf'],", + ")", + "", + "objc_proto_library(", + " name = 'opl',", + " deps = [':protolib'],", + ")", + "", + "objc_proto_library(", + " name = 'nested_opl',", + " deps = [':opl_protobuf'],", + " portable_proto_filters = ['nested_filter.txt'],", + ")", + "", + "objc_proto_library(", + " name = 'opl_protobuf',", + " deps = [':protolib'],", + " portable_proto_filters = [", + " 'proto_filter.txt',", + " ':portable_proto_filters',", + " ],", + ")", + "", + "objc_proto_library(", + " name = 'opl_protobuf_well_known_types',", + " deps = [':protolib_well_known_types'],", + " portable_proto_filters = [", + " 'proto_filter.txt',", + " ],", + ")", + "objc_proto_library(", + " name = 'opl_well_known_types',", + " deps = [':protolib_well_known_types'],", + ")", + "", + "filegroup(", + " name = 'portable_proto_filters',", + " srcs = [", + " 'proto_filter2.txt',", + " 'proto_filter3.txt',", + " ],", + ")", + "", + "proto_library(", + " name = 'protolib',", + " srcs = ['file_a.proto', 'dir/file_b.proto'],", + " deps = ['//dep:dep_lib'],", + ")", + "", + "objc_proto_library(", + " name = 'opl_protobuf_special_names',", + " deps = [':protolib_special_names'],", + " portable_proto_filters = [", + " 'proto_filter.txt',", + " ],", + ")", + "objc_proto_library(", + " name = 'opl_pb2_special_names',", + " deps = [':protolib_special_names'],", + ")", + "", + "proto_library(", + " name = 'protolib_special_names',", + " srcs = [", + " 'j2objc-descriptor.proto',", + " 'http.proto',", + " 'https.proto',", + " 'some_url_blah.proto',", + " 'thumbnail_url.proto',", + " 'url.proto',", + " 'url2https.proto',", + " 'urlbar.proto',", + " ],", + " deps = ['//dep:dep_lib'],", + ")", + "", + "proto_library(", + " name = 'protolib_well_known_types',", + " srcs = ['file_a.proto'],", + " deps = ['//objcproto:well_known_type_proto'],", + ")", + "", + "genrule(", + " name = 'gen_proto',", + " srcs = ['file_a.proto'],", + " outs = ['file_a_genfile.proto'],", + " cmd = 'cp $(location file_a.proto) $(location file_a_genfile.proto)')", + "", + "proto_library(", + " name = 'gen_protolib',", + " srcs = ['file_a_genfile.proto'],", + " deps = ['//dep:dep_lib'],", + ")", + "", + "objc_proto_library(", + " name = 'gen_opl',", + " deps = [':gen_protolib'],", + ")"); + scratch.file("dep/BUILD", + "proto_library(", + " name = 'dep_lib',", + " srcs = ['file.proto'],", + ")"); + scratch.file("package/file_a.proto"); + scratch.file("package/dir/file_b.proto"); + scratch.file("dep/file.proto"); + scratch.file("package/proto_filter.txt"); + scratch.file("package/proto_filter2.txt"); + scratch.file("package/proto_filter3.txt"); + } + + @Test + public void testOutputs() throws Exception { + NestedSet<Artifact> filesToBuild = getFilesToBuild(getConfiguredTarget("//package:opl")); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsAllOf( + "package/libopl.a", + "package/_generated_protos/opl/package/FileA.pb.h", + "package/_generated_protos/opl/package/FileA.pb.m", + "package/_generated_protos/opl/package/dir/FileB.pb.h", + "package/_generated_protos/opl/package/dir/FileB.pb.m", + "package/_generated_protos/opl/dep/File.pb.h"); + } + + @Test + public void testOutputsProtobuf() throws Exception { + NestedSet<Artifact> filesToBuild = + getFilesToBuild(getConfiguredTarget("//package:opl_protobuf")); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsAllOf( + "package/_generated_protos/opl_protobuf/package/FileA.pbobjc.h", + "package/_generated_protos/opl_protobuf/package/FileA.pbobjc.m", + "package/_generated_protos/opl_protobuf/package/dir/FileB.pbobjc.h", + "package/_generated_protos/opl_protobuf/package/dir/FileB.pbobjc.m", + "package/_generated_protos/opl_protobuf/dep/File.pbobjc.h"); + } + + @Test + public void testOutputsWithAutoUnionExperiment() throws Exception { + NestedSet<Artifact> filesToBuild = getFilesToBuild(getConfiguredTarget("//package:opl")); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsAllOf( + "package/libopl.a", + "package/_generated_protos/opl/package/FileA.pb.h", + "package/_generated_protos/opl/package/FileA.pb.m", + "package/_generated_protos/opl/package/dir/FileB.pb.h", + "package/_generated_protos/opl/package/dir/FileB.pb.m", + "package/_generated_protos/opl/dep/File.pb.h"); + } + + @Test + public void testDependingOnProtobufObjcProtoLibrary() throws Exception { + NestedSet<Artifact> filesToBuild = getFilesToBuild(getConfiguredTarget("//package:nested_opl")); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsAllOf( + "package/_generated_protos/nested_opl/package/FileA.pbobjc.h", + "package/_generated_protos/nested_opl/package/FileA.pbobjc.m", + "package/_generated_protos/nested_opl/package/dir/FileB.pbobjc.h", + "package/_generated_protos/nested_opl/package/dir/FileB.pbobjc.m"); + } + + @Test + public void testOutputsProtobufWithAutoUnionExperiment() throws Exception { + NestedSet<Artifact> filesToBuild = + getFilesToBuild(getConfiguredTarget("//package:opl_protobuf")); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .doesNotContain("package/libopl_protobuf.a"); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsAllOf( + "package/_generated_protos/opl_protobuf/package/FileA.pbobjc.h", + "package/_generated_protos/opl_protobuf/package/FileA.pbobjc.m", + "package/_generated_protos/opl_protobuf/package/dir/FileB.pbobjc.h", + "package/_generated_protos/opl_protobuf/package/dir/FileB.pbobjc.m", + "package/_generated_protos/opl_protobuf/dep/File.pbobjc.h"); + } + + @Test + public void testPB2GeneratedFileNames() throws Exception { + NestedSet<Artifact> filesToBuild = + getFilesToBuild(getConfiguredTarget("//package:opl_pb2_special_names")); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsAllOf( + "package/_generated_protos/opl_pb2_special_names/package/J2ObjcDescriptor.pb.h", + "package/_generated_protos/opl_pb2_special_names/package/J2ObjcDescriptor.pb.m", + "package/_generated_protos/opl_pb2_special_names/package/Http.pb.h", + "package/_generated_protos/opl_pb2_special_names/package/Http.pb.m", + "package/_generated_protos/opl_pb2_special_names/package/Https.pb.h", + "package/_generated_protos/opl_pb2_special_names/package/Https.pb.m", + "package/_generated_protos/opl_pb2_special_names/package/SomeUrlBlah.pb.h", + "package/_generated_protos/opl_pb2_special_names/package/SomeUrlBlah.pb.m", + "package/_generated_protos/opl_pb2_special_names/package/ThumbnailUrl.pb.h", + "package/_generated_protos/opl_pb2_special_names/package/ThumbnailUrl.pb.m", + "package/_generated_protos/opl_pb2_special_names/package/Url.pb.h", + "package/_generated_protos/opl_pb2_special_names/package/Url.pb.m", + "package/_generated_protos/opl_pb2_special_names/package/Url2Https.pb.h", + "package/_generated_protos/opl_pb2_special_names/package/Url2Https.pb.m", + "package/_generated_protos/opl_pb2_special_names/package/Urlbar.pb.h", + "package/_generated_protos/opl_pb2_special_names/package/Urlbar.pb.m"); + } + + @Test + public void testProtobufGeneratedFileNames() throws Exception { + NestedSet<Artifact> filesToBuild = + getFilesToBuild(getConfiguredTarget("//package:opl_protobuf_special_names")); + String outputPath = "package/_generated_protos/opl_protobuf_special_names/package/"; + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsAllOf( + outputPath + "J2ObjcDescriptor.pbobjc.h", + outputPath + "J2ObjcDescriptor.pbobjc.m", + outputPath + "HTTP.pbobjc.h", + outputPath + "HTTP.pbobjc.m", + outputPath + "HTTPS.pbobjc.h", + outputPath + "HTTPS.pbobjc.m", + outputPath + "SomeURLBlah.pbobjc.h", + outputPath + "SomeURLBlah.pbobjc.m", + outputPath + "ThumbnailURL.pbobjc.h", + outputPath + "ThumbnailURL.pbobjc.m", + outputPath + "URL.pbobjc.h", + outputPath + "URL.pbobjc.m", + outputPath + "URL2HTTPS.pbobjc.h", + outputPath + "URL2HTTPS.pbobjc.m", + outputPath + "Urlbar.pbobjc.h", + outputPath + "Urlbar.pbobjc.m"); + } + + @Test + public void testOutputsPB2WithWellKnownTypes() throws Exception { + NestedSet<Artifact> filesToBuild = + getFilesToBuild(getConfiguredTarget("//package:opl_well_known_types")); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsAllOf( + "package/_generated_protos/opl_well_known_types/package/FileA.pb.h", + "package/_generated_protos/opl_well_known_types/package/FileA.pb.m"); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsNoneOf( + "package/_generated_protos/opl_well_known_types/objcproto/WellKnownType.pb.h", + "package/_generated_protos/opl_well_known_types/objcproto/WellKnownType.pb.m"); + } + + @Test + public void testOutputsProtobufWithWellKnownTypes() throws Exception { + NestedSet<Artifact> filesToBuild = + getFilesToBuild(getConfiguredTarget("//package:opl_protobuf_well_known_types")); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsAllOf( + "package/_generated_protos/opl_protobuf_well_known_types/package/FileA.pbobjc.h", + "package/_generated_protos/opl_protobuf_well_known_types/package/FileA.pbobjc.m"); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .doesNotContain( + "package/_generated_protos/opl_protobuf_well_known_types/objcproto/WellKnownType.pbobjc.h"); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .doesNotContain( + "package/_generated_protos/opl_protobuf_well_known_types/objcproto/WellKnownType.pbobjc.m"); + } + + @Test + public void testOutputsGenfile() throws Exception { + NestedSet<Artifact> filesToBuild = getFilesToBuild(getConfiguredTarget("//package:gen_opl")); + assertThat(Artifact.toRootRelativePaths(filesToBuild)) + .containsAllOf( + "package/libgen_opl.a", + "package/_generated_protos/gen_opl/package/FileAGenfile.pb.h", + "package/_generated_protos/gen_opl/package/FileAGenfile.pb.m"); + } + + @Test + public void testSourceGenerationAction() throws Exception { + Artifact sourceFile = + ActionsTestUtil.getFirstArtifactEndingWith( + getFilesToBuild(getConfiguredTarget("//package:opl")), "/FileA.pb.m"); + SpawnAction action = (SpawnAction) getGeneratingAction(sourceFile); + + Artifact inputFileList = + ActionsTestUtil.getFirstArtifactEndingWith(action.getInputs(), "/_proto_input_files"); + + ImmutableList<String> protoInputs = + ImmutableList.of("dep/file.proto", "package/file_a.proto", "package/dir/file_b.proto"); + + assertThat(action.getArguments()) + .containsExactly( + "/usr/bin/python", + "tools/objc/compile_protos.py", + "--input-file-list", + inputFileList.getExecPathString(), + "--output-dir", + // 2x parent directory because the package has one element ("package") + sourceFile.getExecPath().getParentDirectory().getParentDirectory().toString(), + "--working-dir", ".") + .inOrder(); + assertRequiresDarwin(action); + assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsAllOf( + "tools/objc/compile_protos.py", + "tools/objc/proto_support"); + assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsAllIn(protoInputs); + assertThat(action.getInputs()).contains(inputFileList); + + FileWriteAction inputListAction = (FileWriteAction) getGeneratingAction(inputFileList); + assertThat(inputListAction.getFileContents()).isEqualTo(sortedJoin(protoInputs)); + } + + @Test + public void testProtobufSourceGenerationAction() throws Exception { + Artifact sourceFile = + ActionsTestUtil.getFirstArtifactEndingWith( + getFilesToBuild(getConfiguredTarget("//package:opl_protobuf")), "/FileA.pbobjc.m"); + SpawnAction action = (SpawnAction) getGeneratingAction(sourceFile); + + Artifact inputFileList = + ActionsTestUtil.getFirstArtifactEndingWith( + action.getInputs(), "/_proto_input_files_BundledProtos_0"); + + ImmutableList<String> protoInputs = + ImmutableList.of("dep/file.proto", "package/file_a.proto", "package/dir/file_b.proto"); + + BuildConfiguration topLevelConfig = getAppleCrosstoolConfiguration(); + assertThat(action.getArguments()) + .containsExactly( + "tools/objc/protobuf_compiler_wrapper.sh", + "--input-file-list", + inputFileList.getExecPathString(), + "--output-dir", + // 2x parent directory because the package has one element ("package") + sourceFile.getExecPath().getParentDirectory().getParentDirectory().toString(), + "--force", + "--proto-root-dir", + topLevelConfig.getGenfilesFragment().toString(), + "--proto-root-dir", + ".", + "--config", + "package/proto_filter.txt", + "--config", + "package/proto_filter2.txt", + "--config", + "package/proto_filter3.txt") + .inOrder(); + assertThat(Artifact.toRootRelativePaths(action.getInputs())) + .containsAllOf( + "tools/objc/protobuf_compiler_wrapper.sh", + "tools/objc/protobuf_compiler_helper.py", + "tools/objc/proto_support"); + assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsAllIn(protoInputs); + assertThat(action.getInputs()).contains(inputFileList); + + FileWriteAction inputListAction = (FileWriteAction) getGeneratingAction(inputFileList); + assertThat(inputListAction.getFileContents()).isEqualTo(sortedJoin(protoInputs)); + } + + @Test + public void testProtobufWithWellKnownTypesProtoListInput() throws Exception { + Artifact sourceFile = + ActionsTestUtil.getFirstArtifactEndingWith( + getFilesToBuild(getConfiguredTarget("//package:opl_protobuf_well_known_types")), + "/FileA.pbobjc.m"); + SpawnAction action = (SpawnAction) getGeneratingAction(sourceFile); + + Artifact inputFileList = + ActionsTestUtil.getFirstArtifactEndingWith( + action.getInputs(), "/_proto_input_files_BundledProtos_0"); + + ImmutableList<String> protoInputs = ImmutableList.of("package/file_a.proto"); + + assertThat(Artifact.toRootRelativePaths(action.getInputs())).containsAllIn(protoInputs); + assertThat(action.getInputs()).contains(inputFileList); + + assertThat(Artifact.toRootRelativePaths(action.getInputs())) + .contains("objcproto/well_known_type.proto"); + + FileWriteAction inputListAction = (FileWriteAction) getGeneratingAction(inputFileList); + assertThat(inputListAction.getFileContents()).isEqualTo(sortedJoin(protoInputs)); + } + + @Test + public void testUseObjcHeaders() throws Exception { + scratch.file("objcheaderpackage/BUILD", + "objc_proto_library(", + " name = 'opl',", + " deps = ['//package:protolib'],", + " use_objc_header_names = 1,", + ")"); + + Artifact sourceFile = + ActionsTestUtil.getFirstArtifactEndingWith( + getFilesToBuild(getConfiguredTarget("//objcheaderpackage:opl")), "/FileA.pb.m"); + SpawnAction action = (SpawnAction) getGeneratingAction(sourceFile); + + assertThat(action.getArguments()).contains("--use-objc-header-names"); + + NestedSet<Artifact> filesToBuild = + getFilesToBuild(getConfiguredTarget("//objcheaderpackage:opl")); + assertThat(Artifact.toRootRelativePaths(filesToBuild)).containsAllOf( + "objcheaderpackage/_generated_protos/opl/package/FileA.pbobjc.h", + "objcheaderpackage/_generated_protos/opl/package/FileA.pb.m", + "objcheaderpackage/_generated_protos/opl/package/dir/FileB.pbobjc.h", + "objcheaderpackage/_generated_protos/opl/package/dir/FileB.pb.m" + ); + } + + @Test + public void testProtobufCompilationAction() throws Exception { + useConfiguration("--ios_cpu=i386"); + + ConfiguredTarget target = getConfiguredTarget("//package:opl_protobuf"); + Artifact sourceFile = + ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), "/FileA.pbobjc.m"); + SpawnAction generateAction = (SpawnAction) getGeneratingAction(sourceFile); + + assertThat(generateAction).isNotNull(); + } + + + @Test + public void testProtobufObjcProviderWithAutoUnionExperiment() throws Exception { + ConfiguredTarget target = getConfiguredTarget("//package:opl_protobuf"); + Artifact headerFile = + ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), "/FileA.pbobjc.h"); + + ObjcProvider provider = providerForTarget("//package:opl_protobuf"); + assertThat(provider.get(ObjcProvider.INCLUDE).toSet()) + .contains(headerFile.getExecPath().getParentDirectory().getParentDirectory()); + + assertThat(provider.get(ObjcProvider.LIBRARY).toSet()) + .doesNotContain(getBinArtifact("libopl_protobuf.a", target)); + + assertThat(provider.get(ObjcProvider.HEADER).toSet()).contains(headerFile); + } + + @Test + public void testPerProtoIncludes() throws Exception { + ConfiguredTarget target = getConfiguredTarget("//package:opl"); + Artifact headerFile = ActionsTestUtil.getFirstArtifactEndingWith( + getFilesToBuild(target), "/FileA.pb.h"); + + ObjcProvider provider = providerForTarget("//package:opl"); + assertThat(provider.get(ObjcProvider.INCLUDE).toSet()).containsExactly( + // 2x parent directory because the package has one element ("package") + headerFile.getExecPath().getParentDirectory().getParentDirectory() + ); + } + + @Test + public void testErrorForNoDepsAttribute() throws Exception { + checkError( + "x", "x", ProtoAttributes.NO_PROTOS_ERROR, "objc_proto_library(", " name = 'x',", ")"); + } + + @Test + public void testErrorForEmptyDepsAttribute() throws Exception { + checkError( + "x", + "x", + ProtoAttributes.NO_PROTOS_ERROR, + "objc_proto_library(", + " name = 'x',", + " deps = [],", + ")"); + } + + // This is a test for deprecated functionality. + @Test + public void testErrorForDepWithFilegroupWithoutProtoFiles() throws Exception { + checkError( + "x", + "x", + ProtoAttributes.NO_PROTOS_ERROR, + "objc_proto_library(", + " name = 'x',", + " deps = [':fg'],", + ")", + "filegroup(", + " name = 'fg',", + " srcs = ['file.dat'],", + ")"); + } + + @Test + public void testWarningForProtoSourceDeps() throws Exception { + checkWarning( + "x", + "x", + ProtoAttributes.FILES_DEPRECATED_WARNING, + "objc_proto_library(", + " name = 'x',", + " deps = ['foo.proto'],", + ")"); + } + + @Test + public void testWarningForFilegroupDeps() throws Exception { + checkWarning( + "x", + "x", + ProtoAttributes.FILES_DEPRECATED_WARNING, + "filegroup(", + " name = 'protos',", + " srcs = ['foo.proto'],", + ")", + "objc_proto_library(", + " name = 'x',", + " deps = [':protos'],", + ")"); + } + + @Test + public void testObjcCopts() throws Exception { + useConfiguration("--objccopt=-foo"); + + List<String> args = compileAction("//package:opl", "FileA.pb.o").getArguments(); + assertThat(args).contains("-foo"); + } + + @Test + public void testObjcCopts_argumentOrdering() throws Exception { + useConfiguration("--objccopt=-foo"); + + List<String> args = compileAction("//package:opl", "FileA.pb.o").getArguments(); + assertThat(args).containsAllOf("-fno-objc-arc", "-foo").inOrder(); + } + + @Test + public void testErrorForPortableProtoFiltersEmpty() throws Exception { + checkError( + "x", + "x", + ProtoAttributes.PORTABLE_PROTO_FILTERS_EMPTY_ERROR, + "objc_proto_library(", + " name = 'x',", + " portable_proto_filters = [],", + " deps = [':protos'],", + ")", + "proto_library(", + " name = 'protos',", + " srcs = ['file.proto'],", + ")"); + } + + @Test + public void testErrorWhenDependingOnPB2FromProtobufTarget() throws Exception { + checkError( + "x", + "x", + ProtoAttributes.PROTOCOL_BUFFERS2_IN_PROTOBUF_DEPS_ERROR, + "objc_proto_library(", + " name = 'x',", + " portable_proto_filters = ['filter.pbascii'],", + " deps = [':pb2', ':protos_b'],", + ")", + "objc_proto_library(", + " name = 'pb2',", + " deps = [':protos_a'],", + ")", + "proto_library(", + " name = 'protos_a',", + " srcs = ['a.proto'],", + ")", + "proto_library(", + " name = 'protos_b',", + " srcs = ['b.proto'],", + ")"); + } + + @Test + public void testErrorWhenDependingOnPB2FromPB2Target() throws Exception { + checkError( + "x", + "x", + ProtoAttributes.OBJC_PROTO_LIB_DEP_IN_PROTOCOL_BUFFERS2_DEPS_ERROR, + "objc_proto_library(", + " name = 'x',", + " deps = [':pb2', ':protos_b'],", + ")", + "objc_proto_library(", + " name = 'pb2',", + " deps = [':protos_a'],", + ")", + "proto_library(", + " name = 'protos_a',", + " srcs = ['a.proto'],", + ")", + "proto_library(", + " name = 'protos_b',", + " srcs = ['b.proto'],", + ")"); + } + + @Test + public void testErrorForPortableProtoFiltersWithUseObjcHeaderNames() throws Exception { + checkErrorForPortableProtoFilterWithPb2Option("use_objc_header_names = 1"); + } + + @Test + public void testErrorForPortableProtoFiltersWithPerProtoIncludes() throws Exception { + checkErrorForPortableProtoFilterWithPb2Option("per_proto_includes = 1"); + } + + @Test + public void testErrorForPortableProtoFiltersWithOptionsFile() throws Exception { + checkErrorForPortableProtoFilterWithPb2Option("options_file = 'options_file.txt'"); + } + + @Test + public void testErrorForUsesProtobufWithUseObjcHeaderNames() throws Exception { + checkErrorForUsesProtobufWithPb2Option("use_objc_header_names = 1"); + } + + @Test + public void testErrorForUsesProtobufWithPerProtoIncludes() throws Exception { + checkErrorForUsesProtobufWithPb2Option("per_proto_includes = 1"); + } + + @Test + public void testErrorForUsesProtobufWithOptionsFile() throws Exception { + checkErrorForUsesProtobufWithPb2Option("options_file = 'options_file.txt'"); + } + + @Test + public void testModulemapCreatedForNonLinkingTargets() throws Exception { + checkOnlyLibModuleMapsArePresentForTarget("//package:opl_protobuf"); + } + + @Test + public void testModulemapNotCreatedForLinkingTargets() throws Exception { + checkOnlyLibModuleMapsArePresentForTarget("//package:opl_binary"); + } + + @Test + public void testErrorForPortableProtoFilterFilesInDeps() throws Exception { + checkError( + "x", + "x", + ProtoAttributes.FILES_NOT_ALLOWED_ERROR, + "objc_proto_library(", + " name = 'x',", + " portable_proto_filters = ['proto_filter.txt'],", + " deps = [':protos'],", + ")", + "filegroup(", + " name = 'protos',", + " srcs = ['file.proto'],", + ")"); + } + + @Test + public void testErrorForUsesProtobufAsFalseWithFilters() throws Exception { + checkError( + "x", + "x", + ProtoAttributes.USES_PROTOBUF_CANT_BE_SPECIFIED_AS_FALSE, + "objc_proto_library(", + " name = 'x',", + " uses_protobuf = 0,", + " portable_proto_filters = ['myfilter.pbascii'],", + " deps = [':protos'],", + ")", + "proto_library(", + " name = 'protos',", + " srcs = ['file.proto'],", + ")"); + } + + private void checkErrorForPortableProtoFilterWithPb2Option(String pb2Option) throws Exception { + checkError( + "x", + "x", + ProtoAttributes.PROTOBUF_ATTRIBUTES_NOT_EXCLUSIVE_ERROR, + "objc_proto_library(", + " name = 'x',", + " portable_proto_filters = ['proto_filter.txt'],", + " " + pb2Option + ",", + " deps = [':protos'],", + ")", + "proto_library(", + " name = 'protos',", + " srcs = ['file.proto'],", + ")"); + } + + private void checkErrorForUsesProtobufWithPb2Option(String pb2Option) throws Exception { + checkError( + "x", + "x", + ProtoAttributes.PROTOBUF_ATTRIBUTES_NOT_EXCLUSIVE_ERROR, + "objc_proto_library(", + " name = 'x',", + " uses_protobuf = 1,", + " " + pb2Option + ",", + " deps = [':protos'],", + ")", + "proto_library(", + " name = 'protos',", + " srcs = ['file.proto'],", + ")"); + } + + private static String sortedJoin(Iterable<String> elements) { + return Joiner.on('\n').join(Ordering.natural().immutableSortedCopy(elements)); + } + + private void checkOnlyLibModuleMapsArePresentForTarget(String target) throws Exception { + Artifact libModuleMap = + getGenfilesArtifact( + "opl_protobuf.modulemaps/module.modulemap", + getConfiguredTarget("//package:opl_protobuf")); + Artifact protolibModuleMap = + getGenfilesArtifact( + "protobuf_lib.modulemaps/module.modulemap", + getConfiguredTarget("//objcproto:protobuf_lib")); + + ObjcProvider provider = providerForTarget(target); + assertThat(Artifact.toRootRelativePaths(provider.get(ObjcProvider.MODULE_MAP).toSet())) + .containsExactlyElementsIn( + Artifact.toRootRelativePaths(ImmutableSet.of(libModuleMap, protolibModuleMap))); + } + + @Test + public void testObjcProvider() throws Exception { + ConfiguredTarget target = getConfiguredTarget("//package:opl"); + Artifact headerFile = + ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), "/FileA.pb.h"); + Artifact sourceFile = + ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), "/FileA.pb.m"); + + ObjcProvider provider = providerForTarget("//package:opl"); + assertThat(provider.get(ObjcProvider.INCLUDE).toSet()) + .contains(headerFile.getExecPath().getParentDirectory().getParentDirectory()); + + ConfiguredTarget libProtoBufTarget = getConfiguredTarget("//objcproto:ProtocolBuffers_lib"); + assertThat(provider.get(ObjcProvider.LIBRARY).toSet()) + .containsExactly( + getBinArtifact("libopl.a", target), + getBinArtifact("libProtocolBuffers_lib.a", libProtoBufTarget)); + + assertThat(provider.get(ObjcProvider.HEADER).toSet()).containsAllOf(headerFile, sourceFile); + + assertThat(provider.get(ObjcProvider.INCLUDE).toSet()) + .contains(headerFile.getExecPath().getParentDirectory().getParentDirectory()); + } + + @Test + public void testProtobufObjcProvider() throws Exception { + ConfiguredTarget target = getConfiguredTarget("//package:opl_protobuf"); + Artifact headerFile = + ActionsTestUtil.getFirstArtifactEndingWith(getFilesToBuild(target), "/FileA.pbobjc.h"); + ObjcProvider provider = providerForTarget("//package:opl_protobuf"); + assertThat(provider.get(ObjcProvider.INCLUDE).toSet()) + .contains(headerFile.getExecPath().getParentDirectory().getParentDirectory()); + + ConfiguredTarget libProtoBufTarget = getConfiguredTarget("//objcproto:protobuf_lib"); + assertThat(provider.get(ObjcProvider.LIBRARY).toSet()) + .containsExactly(getBinArtifact("libprotobuf_lib.a", libProtoBufTarget)); + + assertThat(provider.get(ObjcProvider.HEADER).toSet()).contains(headerFile); + + assertThat(provider.get(ObjcProvider.INCLUDE).toSet()) + .contains(headerFile.getExecPath().getParentDirectory().getParentDirectory()); + } + + @Test + public void testCompilationActionInCoverageMode() throws Exception { + useConfiguration("--collect_code_coverage"); + + ConfiguredTarget target = getConfiguredTarget("//package:opl"); + CommandAction linkAction = + (CommandAction) getGeneratingAction(getBinArtifact("libopl.a", target)); + + CommandAction compileAction = + (CommandAction) + getGeneratingAction( + ActionsTestUtil.getFirstArtifactEndingWith(linkAction.getInputs(), "/FileA.pb.o")); + + assertThat(Artifact.toRootRelativePaths(compileAction.getOutputs())) + .containsAllOf( + "package/_objs/opl/package/_generated_protos/opl/package/FileA.pb.o", + "package/_objs/opl/package/_generated_protos/opl/package/FileA.pb.gcno"); + } + + @Test + public void testModuleMapActionFiltersHeaders() throws Exception { + ConfiguredTarget configuredTarget = getConfiguredTarget("//package:opl"); + Artifact moduleMap = getGenfilesArtifact("opl.modulemaps/module.modulemap", configuredTarget); + + CppModuleMapAction genMap = (CppModuleMapAction) getGeneratingAction(moduleMap); + assertThat(Artifact.toRootRelativePaths(genMap.getPrivateHeaders())).isEmpty(); + assertThat(Artifact.toRootRelativePaths(genMap.getPublicHeaders())) + .containsExactly( + "package/_generated_protos/opl/package/FileA.pb.h", + "package/_generated_protos/opl/package/dir/FileB.pb.h", + "package/_generated_protos/opl/dep/File.pb.h"); + } +} |