• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Protocol Buffers - Google's data interchange format
2# Copyright 2024 Google Inc.  All rights reserved.
3#
4# Use of this source code is governed by a BSD-style
5# license that can be found in the LICENSE file or at
6# https://developers.google.com/open-source/licenses/bsd
7#
8"""Tests for `proto_common.compile` function."""
9
10load("@rules_testing//lib:analysis_test.bzl", "analysis_test", "test_suite")
11load("@rules_testing//lib:truth.bzl", "matching")
12load("@rules_testing//lib:util.bzl", "util")
13load("//bazel:proto_library.bzl", "proto_library")
14load("//bazel/tests/testdata:compile_rule.bzl", "compile_rule")
15
16protocol_compiler = "/protoc"
17
18def proto_common_compile_test_suite(name):
19    util.helper_target(
20        proto_library,
21        name = "simple_proto",
22        srcs = ["A.proto"],
23    )
24    test_suite(
25        name = name,
26        tests = [
27            _test_compile_basic,
28            _test_compile_noplugin,
29            _test_compile_with_plugin_output,
30            _test_compile_with_directory_plugin_output,
31            _test_compile_additional_args,
32            _test_compile_additional_tools,
33            _test_compile_additional_tools_no_plugin,
34            _test_compile_additional_inputs,
35            _test_compile_resource_set,
36            _test_compile_protoc_opts,
37            _test_compile_direct_generated_protos,
38            _test_compile_indirect_generated_protos,
39        ],
40    )
41
42# Verifies basic usage of `proto_common.compile`.
43def _test_compile_basic(name):
44    util.helper_target(
45        compile_rule,
46        name = name + "_compile",
47        proto_dep = ":simple_proto",
48    )
49
50    analysis_test(
51        name = name,
52        target = name + "_compile",
53        impl = _test_compile_basic_impl,
54    )
55
56def _test_compile_basic_impl(env, target):
57    action = env.expect.that_target(target).action_named("MyMnemonic")
58    action.argv().contains_exactly_predicates(
59        [
60            matching.str_endswith(protocol_compiler),
61            matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"),
62            matching.equals_wrapper("-I."),
63            matching.str_endswith("/A.proto"),
64        ],
65    )
66    action.mnemonic().equals("MyMnemonic")
67
68# Verifies usage of proto_common.generate_code with no plugin specified by toolchain.
69def _test_compile_noplugin(name):
70    util.helper_target(
71        compile_rule,
72        name = name + "_compile",
73        proto_dep = ":simple_proto",
74        toolchain = "//bazel/tests/testdata:toolchain_noplugin",
75    )
76
77    analysis_test(
78        name = name,
79        target = name + "_compile",
80        impl = _test_compile_noplugin_impl,
81    )
82
83def _test_compile_noplugin_impl(env, target):
84    action = env.expect.that_target(target).action_named("MyMnemonic")
85    action.argv().contains_exactly_predicates(
86        [
87            matching.str_endswith(protocol_compiler),
88            matching.equals_wrapper("-I."),
89            matching.str_endswith("/A.proto"),
90        ],
91    )
92
93# Verifies usage of `proto_common.compile` with `plugin_output` parameter set to file.
94def _test_compile_with_plugin_output(name):
95    util.helper_target(
96        compile_rule,
97        name = name + "_compile",
98        proto_dep = ":simple_proto",
99        plugin_output = "single",
100    )
101
102    analysis_test(
103        name = name,
104        target = name + "_compile",
105        impl = _test_compile_with_plugin_output_impl,
106    )
107
108def _test_compile_with_plugin_output_impl(env, target):
109    action = env.expect.that_target(target).action_named("MyMnemonic")
110    action.argv().contains_exactly_predicates(
111        [
112            matching.str_endswith(protocol_compiler),
113            matching.str_matches("--java_out=param1,param2:b*-out/*/test_compile_with_plugin_output_compile"),
114            matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"),
115            matching.equals_wrapper("-I."),
116            matching.str_endswith("/A.proto"),
117        ],
118    )
119
120# Verifies usage of `proto_common.compile` with `plugin_output` parameter set to file.
121def _test_compile_with_directory_plugin_output(name):
122    util.helper_target(
123        compile_rule,
124        name = name + "_compile",
125        proto_dep = ":simple_proto",
126        plugin_output = "multiple",
127    )
128
129    analysis_test(
130        name = name,
131        target = name + "_compile",
132        impl = _test_compile_with_directory_plugin_output_impl,
133    )
134
135def _test_compile_with_directory_plugin_output_impl(env, target):
136    action = env.expect.that_target(target).action_named("MyMnemonic")
137    action.argv().contains_exactly_predicates(
138        [
139            matching.str_endswith(protocol_compiler),
140            matching.str_matches("--java_out=param1,param2:b*-out/*/bin"),
141            matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"),
142            matching.equals_wrapper("-I."),
143            matching.str_endswith("/A.proto"),
144        ],
145    )
146
147# Verifies usage of `proto_common.compile` with `additional_args` parameter
148def _test_compile_additional_args(name):
149    util.helper_target(
150        compile_rule,
151        name = name + "_compile",
152        proto_dep = ":simple_proto",
153        additional_args = ["--a", "--b"],
154    )
155
156    analysis_test(
157        name = name,
158        target = name + "_compile",
159        impl = _test_compile_additional_args_impl,
160    )
161
162def _test_compile_additional_args_impl(env, target):
163    action = env.expect.that_target(target).action_named("MyMnemonic")
164    action.argv().contains_exactly_predicates(
165        [
166            matching.str_endswith(protocol_compiler),
167            matching.equals_wrapper("--a"),
168            matching.equals_wrapper("--b"),
169            matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"),
170            matching.equals_wrapper("-I."),
171            matching.str_endswith("/A.proto"),
172        ],
173    )
174
175# Verifies usage of `proto_common.compile` with `additional_tools` parameter
176def _test_compile_additional_tools(name):
177    util.helper_target(
178        compile_rule,
179        name = name + "_compile",
180        proto_dep = ":simple_proto",
181        additional_tools = [
182            "//bazel/tests/testdata:_tool1",
183            "//bazel/tests/testdata:_tool2",
184        ],
185    )
186
187    analysis_test(
188        name = name,
189        target = name + "_compile",
190        impl = _test_compile_additional_tools_impl,
191    )
192
193def _test_compile_additional_tools_impl(env, target):
194    action = env.expect.that_target(target).action_named("MyMnemonic")
195    action.inputs().contains_at_least_predicates(
196        [
197            matching.file_basename_equals("_tool1"),
198            matching.file_basename_equals("_tool2"),
199            matching.file_basename_equals("plugin"),
200        ],
201    )
202
203# Verifies usage of `proto_common.compile` with `additional_tools` parameter and no plugin on the toolchain.
204def _test_compile_additional_tools_no_plugin(name):
205    util.helper_target(
206        compile_rule,
207        name = name + "_compile",
208        proto_dep = ":simple_proto",
209        additional_tools = [
210            "//bazel/tests/testdata:_tool1",
211            "//bazel/tests/testdata:_tool2",
212        ],
213        toolchain = "//bazel/tests/testdata:toolchain_noplugin",
214    )
215
216    analysis_test(
217        name = name,
218        target = name + "_compile",
219        impl = _test_compile_additional_tools_no_plugin_impl,
220    )
221
222def _test_compile_additional_tools_no_plugin_impl(env, target):
223    action = env.expect.that_target(target).action_named("MyMnemonic")
224    action.inputs().contains_at_least_predicates(
225        [
226            matching.file_basename_equals("_tool1"),
227            matching.file_basename_equals("_tool2"),
228        ],
229    )
230    action.inputs().not_contains_predicate(matching.file_basename_equals("plugin"))
231
232# Verifies usage of `proto_common.compile` with `additional_inputs` parameter.
233def _test_compile_additional_inputs(name):
234    util.helper_target(
235        compile_rule,
236        name = name + "_compile",
237        proto_dep = ":simple_proto",
238        additional_inputs = ["input1.txt", "input2.txt"],
239    )
240
241    analysis_test(
242        name = name,
243        target = name + "_compile",
244        impl = _test_compile_additional_inputs_impl,
245    )
246
247def _test_compile_additional_inputs_impl(env, target):
248    action = env.expect.that_target(target).action_named("MyMnemonic")
249    action.inputs().contains_at_least_predicates(
250        [
251            matching.file_basename_equals("input1.txt"),
252            matching.file_basename_equals("input2.txt"),
253        ],
254    )
255
256# Verifies usage of `proto_common.compile` with `additional_tools` parameter and no plugin on the toolchain.
257def _test_compile_resource_set(name):
258    util.helper_target(
259        compile_rule,
260        name = name + "_compile",
261        proto_dep = ":simple_proto",
262        use_resource_set = True,
263    )
264
265    analysis_test(
266        name = name,
267        target = name + "_compile",
268        impl = _test_compile_resource_set_impl,
269    )
270
271def _test_compile_resource_set_impl(env, target):
272    action = env.expect.that_target(target).action_named("MyMnemonic")  # @unused
273    # We can't check the specification of the resource set, but we at least verify analysis passes
274
275# Verifies `--protocopts` are passed to command line.
276def _test_compile_protoc_opts(name):
277    util.helper_target(
278        compile_rule,
279        name = name + "_compile",
280        proto_dep = ":simple_proto",
281    )
282
283    analysis_test(
284        name = name,
285        target = name + "_compile",
286        config_settings = {"//command_line_option:protocopt": ["--foo", "--bar"]},
287        impl = _test_compile_protoc_opts_impl,
288    )
289
290def _test_compile_protoc_opts_impl(env, target):
291    action = env.expect.that_target(target).action_named("MyMnemonic")
292    action.argv().contains_exactly_predicates(
293        [
294            matching.str_endswith(protocol_compiler),
295            matching.equals_wrapper("--foo"),
296            matching.equals_wrapper("--bar"),
297            matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"),
298            matching.equals_wrapper("-I."),
299            matching.str_endswith("/A.proto"),
300        ],
301    )
302
303#  Verifies `proto_common.compile`> correctly handles direct generated `.proto` files.
304def _test_compile_direct_generated_protos(name):
305    util.helper_target(native.genrule, name = name + "_generate_G", cmd = "", outs = ["G.proto"])
306    util.helper_target(
307        proto_library,
308        name = name + "_directly_generated_proto",
309        srcs = ["A.proto", "G.proto"],
310    )
311    util.helper_target(
312        compile_rule,
313        name = name + "_compile",
314        proto_dep = name + "_directly_generated_proto",
315    )
316
317    analysis_test(
318        name = name,
319        target = name + "_compile",
320        impl = _test_compile_direct_generated_protos_impl,
321    )
322
323def _test_compile_direct_generated_protos_impl(env, target):
324    action = env.expect.that_target(target).action_named("MyMnemonic")
325    action.argv().contains_exactly_predicates(
326        [
327            matching.str_endswith(protocol_compiler),
328            matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"),
329            matching.str_matches("-Ib*-out/*/*"),
330            matching.equals_wrapper("-I."),
331            matching.str_endswith("/A.proto"),
332            matching.str_matches("*-out/*/*/*/G.proto"),
333        ],
334    )
335
336# Verifies usage of `proto_common.compile` with `plugin_output` parameter
337def _test_compile_indirect_generated_protos(name):
338    util.helper_target(native.genrule, name = "_generate_h", srcs = ["A.txt"], cmd = "", outs = ["H.proto"])
339    util.helper_target(proto_library, name = "_generated_proto", srcs = ["H.proto"])
340    util.helper_target(
341        proto_library,
342        name = name + "_indirectly_generated_proto",
343        srcs = ["A.proto"],
344        deps = [":_generated_proto"],
345    )
346    util.helper_target(
347        compile_rule,
348        name = name + "_compile",
349        proto_dep = name + "_indirectly_generated_proto",
350    )
351
352    analysis_test(
353        name = name,
354        target = name + "_compile",
355        impl = _test_compile_indirect_generated_protos_impl,
356    )
357
358def _test_compile_indirect_generated_protos_impl(env, target):
359    action = env.expect.that_target(target).action_named("MyMnemonic")
360    action.argv().contains_exactly_predicates(
361        [
362            matching.str_endswith(protocol_compiler),
363            matching.str_matches("--plugin=b*-out/*-exec-*/bin/*/testdata/plugin"),
364            matching.str_matches("-Ib*-out/*/*"),
365            matching.equals_wrapper("-I."),
366            matching.str_endswith("/A.proto"),
367        ],
368    )
369