1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
|
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This file contains templates which are meant to simplify building and
# running test binaries with the Chromecast build infrastructure. See
# documentation above each template for specific use.
#
# Example Usage
#
# # This is a standard test() template from //testing/test.gni. This generates
# # a binary called foo_unittests.
# test("foo_unittests") {
# sources = [ "foo_unittest.cc" ]
#
# deps = [
# ":foo",
# "//testing/gtest",
# "//testing/gmock",
# ]
# }
#
# # And another standard test() target, which generates bar_unittests
# test("bar_unittests") {
# sources = [ "bar_unittest.cc" ]
#
# deps = [ ... ]
# }
#
# # This is an organizational target. This cannot be built directly.
# cast_test_group("cast_tests") {
# tests = [
# ":bar_unittests",
# "//path/to:foo_unittests",
# ]
# }
#
# # Here is another cast_test_group target which builds a bunch of other
# # test binaries, and wants to apply some filters.
# cast_test_group("external_tests") {
# tests = [
# "//path/to/widget:widget_unittests",
# "//even/more/foo:foo_unittests",
# ]
#
# filters = [
# "widget_unittests --gtest_filter=-WidgetTest.TestToBeFiltered",
# ]
# }
#
# # Build this to create build and run lists for bar and foo tests.
# cast_test_group_list("cast_test_lists") {
# test_groups = [
# ":cast_tests",
# ":external_tests",
# ]
#
# build_list_paths = "$root_out_dir/path/to/test/build_list.txt"
#
# run_list_path = "$root_out_dir/path/to/list/run_list.txt"
# }
import("//testing/test.gni")
# This directory must be the same for every cast_test_group instance.
_shared_dir = "$root_gen_dir/chromecast/tests"
# A group of test executables. Including test targets in this group makes it
# possible for Chromecast build infrastructure to build and run them with
# filters. To accomplish this, it defines two actions, one which generates a
# build list of all |tests|, and one which generates a run list of all |tests|.
# It also creates a group with dependencies on each test, to ensure that they
# are valid targets. Do not build these targets. Build cast_test_group_list
# instead.
#
# Parameters
# tests (required)
# A list of test targets included in the assembly. Do not include any
# other type of target. Each target's name must match the name of the
# executable it builds.
#
# filters (optional)
# A list of strings of format: "<test_name> --gtest_filter=<filter_logic>"
# The <test_name> used must correspond to a test in |tests|. Please see
# //chromecast/tools/build/generate_test_lists.py for more information.
# If this is not defined, no filters are applied.
#
# priority (optional)
# A string which takes any single-digit integer bewtween "1" and "9",
# inclusive. Assign this to prioritize filters applied by other
# cast_test_groups, where a higher number trumps a lower number.
# If not assigned, priority defaults to "1", the lowest priority.
#
template("cast_test_group") {
assert(defined(invoker.tests),
"$target_name needs 'tests' listing the test() targets")
# If a set of filters has not been defined, use the empty list.
_filters = []
if (defined(invoker.filters)) {
_filters = invoker.filters
}
# If priority has not been set, set the priority to "1", the lowest priority.
_priority = "1"
if (defined(invoker.priority)) {
_priority = invoker.priority
}
# Assert that |_priority| is an integer between "1" and "9", inclusive.
assert(_priority == "1" || _priority == "2" || _priority == "3" ||
_priority == "4" || _priority == "5" || _priority == "6" ||
_priority == "7" || _priority == "8" || _priority == "9")
# This will be the prefix of each output file.
_output_prefix = "$_shared_dir/$_priority-$target_name"
# Create a list of all the target names. These must correspond to the name of
# the test binary.
_test_names = []
foreach(_test, invoker.tests) {
_test_names += [ get_label_info(_test, "name") ]
}
# This action generates a list of target names to build and run. It will be
# depended upon by the "pack_build" action of the cast_test_group_list
# instance which depends on this cast_test_group.
action(target_name + "_create_list") {
script = "//chromecast/tools/build/generate_test_lists.py"
outputs = [
"$_output_prefix.tests",
]
args = [
"-o",
rebase_path("$_output_prefix.tests"),
"create_list",
]
args += _test_names
}
# This action generates a list of test filters, which will have a priority
# [1-9]. This will be depended upon by the "pack_run" action of the
# cast_test_group_list which depends on this group.
action(target_name + "_filters") {
script = "//chromecast/tools/build/generate_test_lists.py"
outputs = [
"$_output_prefix.filters",
]
args = [
"-o",
rebase_path("$_output_prefix.filters"),
"create_list",
]
args += _filters
}
# This target allows us to reference each test as a fully-qualified GN path,
# to ensure that each path is correct. If a test does not exist, gives a
# helpful error message at the line it is included. Do not build this target
# directly.
group(target_name + "_build_tests") {
testonly = true
deps = invoker.tests
}
}
# This template runs a script which generates lists of test to be built and run.
#
# Parameters
# test_groups (required)
# The cast_test_group() targets for which this binary is to be created.
# The targets referenced here must be cast_test_group targets, or buiding
# this target will fail.
#
# build_list_path (required)
# The absolute filepath of the output file which will hold the list of
# tests to be built.
#
# run_list_path (required)
# The absolute filepath of the output file which will hold the list of
# tests to be run, each with filters assigned by cast_groups.
#
# additional_options (optional)
# Options which are passed to the python script, and applied to every test
#
# build_tests (optional)
# Set this to true to build all of the tests included in |test_groups|.
# Defaults to false. Note that if this is set to true, the test targets
# will be built after all the lists are generated.
#
template("cast_test_group_list") {
assert(defined(invoker.test_groups), "$target_name needs 'test_groups'")
assert(defined(invoker.run_list_path), "$target_name needs 'run_list_path'")
assert(defined(invoker.build_list_path),
"$target_name needs 'build_list_path'")
_pack_build_action = target_name + "_pack_build"
# Generate a list of the "create_list" actions for each group. These will be
# depended upon to ensure they're run before the "pack_build" step.
_build_actions = []
foreach(_test_group, invoker.test_groups) {
_build_actions += [ _test_group + "_create_list" ]
}
# Generate a list of the "filter" actions for each group. These will be
# depended upon to ensure they're run before the "pack_run" step.
_filter_actions = []
foreach(_test_group, invoker.test_groups) {
_filter_actions += [ _test_group + "_filters" ]
}
# Generate a list of the groups of targets, so that they can be depended upon
# by the "pack_run" step and built when this target is invoked.
if (defined(invoker.build_tests) && invoker.build_tests) {
_build_tests = []
foreach(_test_group, invoker.test_groups) {
_build_tests += [ _test_group + "_build_tests" ]
}
}
# The "pack_build" step. This step looks in the common folder for files with
# the ".tests" extenstion, collecting these and packing them into an output
# file. The steps which create these files are depeneded upon, to ensure
# they're run before this step. Do not invoke this target directly.
action(_pack_build_action) {
script = "//chromecast/tools/build/generate_test_lists.py"
outputs = [
invoker.build_list_path,
]
args = [
"-o",
rebase_path(invoker.build_list_path),
"-t",
rebase_path(_shared_dir),
"pack_build",
]
deps = _build_actions
}
# The "pack_run" step. This step looks in the common folder for files with
# the ".tests" and ".filters" extensions, creating a script of tests to run,
# with filters and priorities. See
# //chromecast/tools/build/generate_test_lists.py for more information.
# Note that this target takes the name of the invoker, such that invoking the
# target runs this step.
action(target_name) {
testonly = true
script = "//chromecast/tools/build/generate_test_lists.py"
outputs = [
invoker.run_list_path,
]
args = [
"-o",
rebase_path(invoker.run_list_path),
"-t",
rebase_path(_shared_dir),
"pack_run",
]
# Add addtional options if they have been set.
if (defined(invoker.additional_options)) {
args += [ "-a" ]
args += invoker.additional_options
}
# Depend first on the "pack_build" step, so that the build lists are created.
deps = [
":$_pack_build_action",
]
# Next, depend on the filter steps, such that they are created before this
# script executes.
deps += _filter_actions
# If |build_tests| has been set to true, depend on the testing targets so
# that the tests are built.
if (defined(_build_tests)) {
deps += _build_tests
}
}
}
|