blob: f2883413c00ac59a41354c620a718c03f8e64d75 [file] [log] [blame]
Alexei Frolov925fb8f2019-11-05 16:32:30 -08001# Copyright 2019 The Pigweed Authors
2#
3# Licensed under the Apache License, Version 2.0 (the "License"); you may not
4# use this file except in compliance with the License. You may obtain a copy of
5# the License at
6#
7# https://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14
Armando Montanezfb3d3fb2020-06-09 18:12:12 -070015# gn-format disable
16import("//build_overrides/pigweed.gni")
17
Alexei Frolovd1f98fa2019-11-08 15:41:37 -080018import("$dir_pw_build/python_script.gni")
Alexei Frolovedd2f142020-06-09 19:11:27 -070019import("$dir_pw_build/target_types.gni")
Alexei Frolov4c0428a2020-06-10 10:46:04 -070020declare_args() {
21 # Path to a test runner to automatically run unit tests after they are built.
22 #
23 # If set, the pw_test() template creates an action that invokes the test runner
24 # on each test executable. If unset, the pw_test() template only creates a test
25 # executable target.
26 #
27 # This should only be enabled for targets which support parallelized running of
28 # unit tests, such as desktops with multiple cores.
29 pw_unit_test_AUTOMATIC_RUNNER = ""
30
31 # Implementation of a main function for "pw_test" unit test binaries.
32 pw_unit_test_MAIN = "$dir_pw_unit_test:simple_printing_main"
33}
Alexei Frolov925fb8f2019-11-05 16:32:30 -080034
Wyatt Heplerdfe3c612020-04-23 13:13:45 -070035# Defines a target if enable_if is true. Otherwise, it defines that target as
36# <target_name>_DISABLED and creates an empty <target_name> group. This can be
37# used to conditionally create targets without having to conditionally add them
38# to groups. This results in simpler BUILD.gn files.
39template("_pw_disableable_target") {
40 assert(defined(invoker.enable_if),
41 "`enable_if` is required for _pw_disableable_target")
42 assert(defined(invoker.target_type),
43 "`target_type` is required for _pw_disableable_target")
44
45 if (invoker.enable_if) {
46 _actual_target_name = target_name
47 } else {
48 _actual_target_name = target_name + "_DISABLED"
49
Wyatt Hepler4e6a4722020-07-09 17:34:48 -070050 # If the target is disabled, create an empty target in its place. Use an
51 # action with the original target's sources as inputs to ensure that
52 # the source files exist (even if they don't compile).
53 pw_python_script(target_name) {
Wyatt Hepler27f69f02020-07-27 09:06:21 -070054 script = "$dir_pw_build/py/pw_build/nop.py"
Wyatt Hepler4e6a4722020-07-09 17:34:48 -070055 stamp = true
56
57 inputs = []
58 if (defined(invoker.sources)) {
59 inputs += invoker.sources
60 }
61 if (defined(invoker.public)) {
62 inputs += invoker.public
63 }
Wyatt Heplerdfe3c612020-04-23 13:13:45 -070064 }
65 }
66
67 target(invoker.target_type, _actual_target_name) {
68 forward_variables_from(invoker,
69 "*",
70 [
71 "enable_if",
72 "target_type",
73 ])
Wyatt Hepler68fde052020-05-13 14:43:03 -070074
75 # Remove "" from dependencies. This allows disabling targets if a variable
76 # (e.g. a backend) is empty.
77 if (defined(public_deps)) {
78 public_deps += [ "" ]
79 public_deps -= [ "" ]
80 }
81 if (defined(deps)) {
82 deps += [ "" ]
83 deps -= [ "" ]
84 }
Wyatt Heplerdfe3c612020-04-23 13:13:45 -070085 }
86}
87
Alexei Frolov925fb8f2019-11-05 16:32:30 -080088# Creates an executable target for a unit test.
Alexei Frolova454c682019-11-19 10:55:07 -080089#
Alexei Frolov4c0428a2020-06-10 10:46:04 -070090# If the pw_unit_test_AUTOMATIC_RUNNER variable is set, this template also creates a
Alexei Frolov8403f0a2019-11-20 13:57:54 -080091# "${test_name}_run" target which runs the unit test executable after building
92# it.
Alexei Frolov925fb8f2019-11-05 16:32:30 -080093#
Wyatt Heplerdfe3c612020-04-23 13:13:45 -070094# Args:
95# - enable_if: (optional) Conditionally enables or disables this test. The test
96# target and *_run target do nothing when the test is disabled. The
97# disabled test can still be built and run with the
98# <target_name>_DISABLED and <target_name>_DISABLED_run targets.
99# Defaults to true (enable_if).
100# - All of the regular "executable" target args are accepted.
Alexei Frolov925fb8f2019-11-05 16:32:30 -0800101template("pw_test") {
102 # This is required in order to reference the pw_test template's target name
103 # within the test_metadata of the metadata group below. The group() definition
104 # creates a new scope where the "target_name" variable is set to its target,
105 # shadowing the one in this scope.
Alexei Frolovd1f98fa2019-11-08 15:41:37 -0800106 _test_target_name = target_name
Alexei Frolov925fb8f2019-11-05 16:32:30 -0800107
Wyatt Heplerdfe3c612020-04-23 13:13:45 -0700108 _test_is_enabled = !defined(invoker.enable_if) || invoker.enable_if
109
Michael Spang524ead42020-06-12 14:23:40 -0400110 # Always set the output_dir as pigweed is not compatible with shared
111 # bin directories for tests.
Michael Spangcdba5162020-06-12 14:45:07 -0400112 _test_output_dir = "${target_out_dir}/test"
Michael Spang524ead42020-06-12 14:23:40 -0400113 if (defined(invoker.output_dir)) {
114 _test_output_dir = invoker.output_dir
115 }
116
Michael Spang6aa8eb02020-06-11 20:19:05 -0400117 _test_main = pw_unit_test_MAIN
118 if (defined(invoker.test_main)) {
119 _test_main = invoker.test_main
120 }
121
Wyatt Heplerdfe3c612020-04-23 13:13:45 -0700122 _pw_disableable_target(_test_target_name) {
123 target_type = "pw_executable"
124 enable_if = _test_is_enabled
125
Alexei Frolova454c682019-11-19 10:55:07 -0800126 # Metadata for this test when used as part of a pw_test_group target.
Alexei Frolov925fb8f2019-11-05 16:32:30 -0800127 metadata = {
Alexei Frolova454c682019-11-19 10:55:07 -0800128 tests = [
Alexei Frolov925fb8f2019-11-05 16:32:30 -0800129 {
Alexei Frolova454c682019-11-19 10:55:07 -0800130 type = "test"
Alexei Frolovd1f98fa2019-11-08 15:41:37 -0800131 test_name = _test_target_name
Michael Spang524ead42020-06-12 14:23:40 -0400132 test_directory = rebase_path(_test_output_dir, root_build_dir)
Alexei Frolov925fb8f2019-11-05 16:32:30 -0800133 },
134 ]
135 }
Alexei Frolov925fb8f2019-11-05 16:32:30 -0800136
Alexei Frolova454c682019-11-19 10:55:07 -0800137 forward_variables_from(invoker, "*", [ "metadata" ])
Paul Mathieu97b967a2019-11-21 09:01:03 -0800138
139 if (!defined(deps)) {
140 deps = []
141 }
Michael Spang6aa8eb02020-06-11 20:19:05 -0400142 if (_test_main != "") {
143 deps += [ _test_main ]
144 }
Michael Spang524ead42020-06-12 14:23:40 -0400145
146 output_dir = _test_output_dir
Alexei Frolov925fb8f2019-11-05 16:32:30 -0800147 }
148
Alexei Frolov4c0428a2020-06-10 10:46:04 -0700149 if (pw_unit_test_AUTOMATIC_RUNNER != "") {
Alexei Frolov8403f0a2019-11-20 13:57:54 -0800150 # When the automatic runner is set, create an action which runs the unit
151 # test executable using the test runner script.
Wyatt Heplerdfe3c612020-04-23 13:13:45 -0700152 if (_test_is_enabled) {
153 _test_to_run = _test_target_name
154 } else {
155 # Create a run target for the _DISABLED version of the test.
156 _test_to_run = _test_target_name + "_DISABLED"
Alexei Frolov925fb8f2019-11-05 16:32:30 -0800157
Wyatt Heplerdfe3c612020-04-23 13:13:45 -0700158 # Create a dummy _run target for the regular version of the test.
159 group(_test_target_name + "_run") {
160 deps = [ ":$_test_target_name" ]
161 }
162 }
163
164 pw_python_script(_test_to_run + "_run") {
Rob Mohra0ba54f2020-02-27 11:43:49 -0800165 deps = [ ":$_test_target_name" ]
Alexei Frolov4c0428a2020-06-10 10:46:04 -0700166 inputs = [ pw_unit_test_AUTOMATIC_RUNNER ]
Alexei Frolov3dbfcf02019-11-22 16:38:02 -0800167 script = "$dir_pw_unit_test/py/pw_unit_test/test_runner.py"
Alexei Frolov8403f0a2019-11-20 13:57:54 -0800168 args = [
169 "--runner",
Alexei Frolov4c0428a2020-06-10 10:46:04 -0700170 pw_unit_test_AUTOMATIC_RUNNER,
Alexei Frolov8403f0a2019-11-20 13:57:54 -0800171 "--test",
Michael Spang524ead42020-06-12 14:23:40 -0400172 get_path_info("$_test_output_dir:$_test_to_run", "abspath"),
Alexei Frolov8403f0a2019-11-20 13:57:54 -0800173 ]
Alexei Frolov917756d2019-11-12 14:34:34 -0800174 stamp = true
Alexei Frolov925fb8f2019-11-05 16:32:30 -0800175 }
176 }
177}
Alexei Frolova454c682019-11-19 10:55:07 -0800178
179# Defines a related collection of unit tests.
180#
181# pw_test_group targets output a JSON metadata file for the Pigweed test runner.
182#
183# Args:
Alexei Frolovbcac2c92020-05-19 10:24:20 -0700184# - tests: List of pw_test targets for each of the tests in the group.
185# - group_deps: (optional) pw_test_group targets on which this group depends.
186# - enable_if: (optional) Conditionally enables or disables this test group.
187# If false, an empty group is created. Defaults to true.
Alexei Frolova454c682019-11-19 10:55:07 -0800188template("pw_test_group") {
Alexei Frolov8403f0a2019-11-20 13:57:54 -0800189 _group_target = target_name
190 _group_deps_metadata = []
Wyatt Hepleredf6f292019-11-25 18:52:21 -0800191 if (defined(invoker.tests)) {
192 _deps = invoker.tests
193 } else {
194 _deps = []
195 }
Alexei Frolov8403f0a2019-11-20 13:57:54 -0800196
Alexei Frolovbcac2c92020-05-19 10:24:20 -0700197 _group_is_enabled = !defined(invoker.enable_if) || invoker.enable_if
198
199 if (_group_is_enabled) {
200 if (defined(invoker.group_deps)) {
201 # If the group specified any other group dependencies, create a metadata
202 # entry for each of them indicating that they are another group and a
203 # group target to collect that metadata.
204 foreach(dep, invoker.group_deps) {
205 _group_deps_metadata += [
206 {
207 type = "dep"
208 group = get_path_info(dep, "abspath")
209 },
210 ]
211 }
212
213 _deps += invoker.group_deps
Alexei Frolova454c682019-11-19 10:55:07 -0800214 }
215
Alexei Frolovbcac2c92020-05-19 10:24:20 -0700216 _metadata_group_target = "${target_name}_pw_test_group_metadata"
217 group(_metadata_group_target) {
218 metadata = {
219 group_deps = _group_deps_metadata
220 self = [
221 {
222 type = "self"
223 name = get_path_info(":$_group_target", "abspath")
224 },
225 ]
Alexei Frolova454c682019-11-19 10:55:07 -0800226
Alexei Frolovbcac2c92020-05-19 10:24:20 -0700227 # Metadata from the group's own unit test targets is forwarded through
228 # the group dependencies group. This entry is listed as a "walk_key" in
229 # the generated file so that only test targets' metadata (not group
230 # targets) appear in the output.
231 if (defined(invoker.tests)) {
232 propagate_metadata_from = invoker.tests
233 }
234 }
235 deps = _deps
236 }
237
238 _test_group_deps = [ ":$_metadata_group_target" ]
239
240 generated_file(_group_target) {
241 outputs = [ "$target_out_dir/$target_name.testinfo.json" ]
242 data_keys = [
243 "group_deps",
244 "self",
245 "tests",
Alexei Frolov8403f0a2019-11-20 13:57:54 -0800246 ]
Alexei Frolovbcac2c92020-05-19 10:24:20 -0700247 walk_keys = [ "propagate_metadata_from" ]
248 output_conversion = "json"
249 deps = _test_group_deps
250 }
Alexei Frolov8403f0a2019-11-20 13:57:54 -0800251
Alexei Frolovbcac2c92020-05-19 10:24:20 -0700252 # If automatic test running is enabled, create a *_run group that collects
253 # all of the individual *_run targets and groups.
Alexei Frolov4c0428a2020-06-10 10:46:04 -0700254 if (pw_unit_test_AUTOMATIC_RUNNER != "") {
Alexei Frolovbcac2c92020-05-19 10:24:20 -0700255 group(_group_target + "_run") {
256 deps = [ ":$_group_target" ]
257 foreach(_target, _deps) {
258 deps += [ "${_target}_run" ]
259 }
Wyatt Hepleredf6f292019-11-25 18:52:21 -0800260 }
Alexei Frolov8403f0a2019-11-20 13:57:54 -0800261 }
Alexei Frolovbcac2c92020-05-19 10:24:20 -0700262 } else { # _group_is_enabled
263 # Create empty groups for the tests to avoid pulling in any dependencies.
264 group(_group_target) {
265 }
Alexei Frolov8403f0a2019-11-20 13:57:54 -0800266
Alexei Frolov4c0428a2020-06-10 10:46:04 -0700267 if (pw_unit_test_AUTOMATIC_RUNNER != "") {
Alexei Frolovbcac2c92020-05-19 10:24:20 -0700268 group(_group_target + "_run") {
Wyatt Hepleredf6f292019-11-25 18:52:21 -0800269 }
270 }
Alexei Frolovbcac2c92020-05-19 10:24:20 -0700271
272 not_needed("*")
273 not_needed(invoker, "*")
Wyatt Hepleredf6f292019-11-25 18:52:21 -0800274 }
Alexei Frolova454c682019-11-19 10:55:07 -0800275}