1# Copyright 2015 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5# ==============================================================================
6# TEST SETUP
7# ==============================================================================
8
9template("_gen_isolate") {
10  testonly = true
11  _runtime_deps_file = "$target_gen_dir/$target_name.runtime_deps"
12  group("${target_name}__write_deps") {
13    forward_variables_from(invoker,
14                           [
15                             "data",
16                             "data_deps",
17                             "deps",
18                             "public_deps",
19                           ])
20    write_runtime_deps = _runtime_deps_file
21  }
22
23  action(target_name) {
24    script = "//testing/generate_isolate.py"
25    inputs = [
26      _runtime_deps_file,
27    ]
28    outputs = [
29      invoker.output,
30    ]
31    args = [
32      "--output-directory=.",
33      "--out-file",
34      rebase_path(invoker.output, root_build_dir),
35      "--runtime-deps-file",
36      rebase_path(_runtime_deps_file, root_build_dir),
37    ]
38    if (is_android) {
39      args += [ "--apply-android-filters" ]
40    }
41    if (defined(invoker.apply_device_filters) && invoker.apply_device_filters) {
42      args += [ "--apply-device-filters" ]
43    }
44    _assert_no_odd_data =
45        defined(invoker.assert_no_odd_data) && invoker.assert_no_odd_data
46    if (_assert_no_odd_data) {
47      args += [ "--assert-no-odd-data" ]
48    }
49    if (defined(invoker.command)) {
50      _isolate_dir = get_path_info(invoker.output, "dir")
51      args += [
52        "--command",
53        rebase_path(invoker.command, _isolate_dir),
54      ]
55    }
56    deps = [
57      ":${invoker.target_name}__write_deps",
58    ]
59  }
60}
61
62# Define a test as an executable (or apk on Android) with the "testonly" flag
63# set.
64# Variable:
65#   use_raw_android_executable: Use executable() rather than android_apk().
66#   use_native_activity: Test implements ANativeActivity_onCreate().
67template("test") {
68  if (is_android) {
69    import("//build/config/android/config.gni")
70    import("//build/config/android/rules.gni")
71    import("//build/config/sanitizers/sanitizers.gni")
72
73    _use_raw_android_executable = defined(invoker.use_raw_android_executable) &&
74                                  invoker.use_raw_android_executable
75
76    # output_name is used to allow targets with the same name but in different
77    # packages to still produce unique runner scripts.
78    _output_name = invoker.target_name
79    if (defined(invoker.output_name)) {
80      _output_name = invoker.output_name
81    }
82
83    _test_runner_target = "${_output_name}__test_runner_script"
84    _wrapper_script_vars = [ "shard_timeout" ]
85    _gen_isolate_vars = [
86      "allow_odd_runtime_deps",
87      "ignore_all_data_deps",
88    ]
89    _generate_device_isolate =
90        !defined(invoker.ignore_all_data_deps) || !invoker.ignore_all_data_deps
91
92    if (_generate_device_isolate) {
93      _allow_odd_runtime_deps = defined(invoker.allow_odd_runtime_deps) &&
94                                invoker.allow_odd_runtime_deps
95
96      # The device isolate is needed at runtime, so it cannot go in
97      # target_gen_dir, as builder/tester configurations do not include it.
98      _target_dir_name = get_label_info(":$target_name", "dir")
99      _device_isolate_path = "$root_out_dir/gen.runtime/$_target_dir_name/$target_name.device.isolate"
100      _gen_isolate_target_name = "${target_name}__isolate"
101      _gen_isolate(_gen_isolate_target_name) {
102        forward_variables_from(invoker,
103                               [
104                                 "data",
105                                 "data_deps",
106                                 "deps",
107                                 "public_deps",
108                               ])
109        assert_no_odd_data = !_allow_odd_runtime_deps
110        output = _device_isolate_path
111        apply_device_filters = true
112      }
113    }
114
115    assert(_use_raw_android_executable || enable_java_templates)
116
117    if (_use_raw_android_executable) {
118      _exec_target = "${target_name}__exec"
119      _dist_target = "${target_name}__dist"
120      _exec_output =
121          "$target_out_dir/${invoker.target_name}/${invoker.target_name}"
122
123      executable(_exec_target) {
124        # Configs will always be defined since we set_defaults in BUILDCONFIG.gn.
125        configs = []
126        data_deps = []
127        forward_variables_from(
128            invoker,
129            "*",
130            _wrapper_script_vars + _gen_isolate_vars + [ "extra_dist_files" ])
131        testonly = true
132
133        # Thanks to the set_defaults() for test(), configs are initialized with
134        # the default shared_library configs rather than executable configs.
135        configs -= [
136          "//build/config:shared_library_config",
137          "//build/config/android:hide_native_jni_exports",
138        ]
139        configs += [ "//build/config:executable_config" ]
140
141        # Don't output to the root or else conflict with the group() below.
142        output_name = rebase_path(_exec_output, root_out_dir)
143        if (is_component_build || is_asan) {
144          data_deps += [ "//build/android:cpplib_stripped" ]
145        }
146      }
147
148      create_native_executable_dist(_dist_target) {
149        testonly = true
150        dist_dir = "$root_out_dir/$target_name"
151        binary = _exec_output
152        deps = [
153          ":$_exec_target",
154        ]
155        if (defined(invoker.extra_dist_files)) {
156          extra_files = invoker.extra_dist_files
157        }
158      }
159    } else {
160      _library_target = "_${target_name}__library"
161      _apk_target = "${target_name}_apk"
162      _apk_specific_vars = [
163        "android_manifest",
164        "enable_multidex",
165        "proguard_configs",
166        "proguard_enabled",
167        "use_default_launcher",
168        "write_asset_list",
169        "use_native_activity",
170      ]
171      shared_library(_library_target) {
172        # Configs will always be defined since we set_defaults in BUILDCONFIG.gn.
173        configs = []  # Prevent list overwriting warning.
174        configs = invoker.configs
175        testonly = true
176
177        deps = []
178        forward_variables_from(invoker,
179                               "*",
180                               _apk_specific_vars + _wrapper_script_vars +
181                                   _gen_isolate_vars + [ "visibility" ])
182
183        if (!defined(invoker.use_default_launcher) ||
184            invoker.use_default_launcher) {
185          deps += [ "//testing/android/native_test:native_test_native_code" ]
186        }
187      }
188      unittest_apk(_apk_target) {
189        forward_variables_from(invoker, _apk_specific_vars + [ "deps" ])
190        unittests_dep = ":$_library_target"
191        apk_name = invoker.target_name
192        if (defined(invoker.output_name)) {
193          apk_name = invoker.output_name
194          unittests_binary = "lib${apk_name}.so"
195          install_script_name = "install_${invoker.output_name}"
196        }
197        deps += [ ":$_library_target" ]
198
199        # TODO(agrieve): Remove this data_dep once bots don't build the _apk
200        #     target (post-GYP).
201        # It's a bit backwards for the apk to depend on the runner script, since
202        # the apk is conceptually a runtime_dep of the script. However, it is
203        # currently necessary because the bots build this _apk target directly
204        # rather than the group() below.
205        data_deps = [
206          ":$_test_runner_target",
207        ]
208      }
209
210      # Incremental test targets work only for .apks.
211      _incremental_test_runner_target =
212          "${_output_name}_incremental__test_runner_script"
213      test_runner_script(_incremental_test_runner_target) {
214        forward_variables_from(invoker, _wrapper_script_vars)
215        if (_generate_device_isolate) {
216          isolate_file = _device_isolate_path
217          deps = [
218            ":$_gen_isolate_target_name",
219          ]
220        }
221        apk_target = ":$_apk_target"
222        test_name = "${_output_name}_incremental"
223        test_type = "gtest"
224        test_suite = _output_name
225        incremental_install = true
226      }
227      group("${target_name}_incremental") {
228        testonly = true
229        datadeps = [
230          ":$_incremental_test_runner_target",
231        ]
232        deps = [
233          ":${_apk_target}_incremental",
234        ]
235      }
236    }
237
238    _test_runner_target = "${_output_name}__test_runner_script"
239    test_runner_script(_test_runner_target) {
240      forward_variables_from(invoker, _wrapper_script_vars)
241      if (_generate_device_isolate) {
242        isolate_file = _device_isolate_path
243        deps = [
244          ":$_gen_isolate_target_name",
245        ]
246      }
247
248      if (_use_raw_android_executable) {
249        executable_dist_dir = "$root_out_dir/$_dist_target"
250      } else {
251        apk_target = ":$_apk_target"
252      }
253      test_name = _output_name
254      test_type = "gtest"
255      test_suite = _output_name
256    }
257
258    group(target_name) {
259      testonly = true
260      deps = [
261        ":$_test_runner_target",
262      ]
263      if (_use_raw_android_executable) {
264        deps += [ ":$_dist_target" ]
265      } else {
266        deps += [ ":$_apk_target" ]
267      }
268    }
269
270    # TODO(GYP_GONE): Delete this after we've converted everything to GN.
271    # The _run targets exist only for compatibility w/ GYP.
272    group("${target_name}_apk_run") {
273      testonly = true
274      deps = [
275        ":${invoker.target_name}",
276      ]
277    }
278  } else if (is_ios) {
279    import("//build/config/ios/rules.gni")
280
281    _test_target = target_name
282    _resources_bundle_data = target_name + "_resources_bundle_data"
283
284    bundle_data(_resources_bundle_data) {
285      visibility = [
286        ":${_test_target}",
287        ":${_test_target}_generate_executable",
288      ]
289      sources = [
290        "//testing/gtest_ios/Default.png",
291      ]
292      outputs = [
293        "{{bundle_resources_dir}}/{{source_file_part}}",
294      ]
295    }
296
297    ios_app_bundle(_test_target) {
298      testonly = true
299
300      # See above call.
301      set_sources_assignment_filter([])
302      forward_variables_from(invoker, "*", [ "testonly" ])
303
304      # Provide sensible defaults in case invoker did not define any of those
305      # required variables.
306      if (!defined(info_plist) && !defined(info_plist_target)) {
307        info_plist = "//testing/gtest_ios/unittest-Info.plist"
308      }
309      if (!defined(entitlements_path)) {
310        entitlements_path = "//testing/gtest_ios"
311      }
312      if (!defined(code_signing_identity)) {
313        code_signing_identity = ""
314      }
315
316      # TODO(crbug.com/603102): remove this once gyp support is dropped and all
317      # application uses the target name as value for BUNDLE_ID_TEST_NAME.
318      if (defined(invoker.app_name)) {
319        app_name = invoker.app_name
320      } else {
321        app_name = target_name
322      }
323
324      if (!defined(extra_substitutions)) {
325        extra_substitutions = []
326      }
327      extra_substitutions += [ "BUNDLE_ID_TEST_NAME=$app_name" ]
328
329      if (!defined(deps)) {
330        deps = []
331      }
332      deps += [
333        ":$_resources_bundle_data",
334
335        # All shared libraries must have the sanitizer deps to properly link in
336        # asan mode (this target will be empty in other cases).
337        "//build/config/sanitizers:deps",
338      ]
339    }
340  } else {
341    executable(target_name) {
342      deps = []
343      forward_variables_from(invoker, "*")
344
345      testonly = true
346      deps += [
347        # All shared libraries must have the sanitizer deps to properly link in
348        # asan mode (this target will be empty in other cases).
349        "//build/config/sanitizers:deps",
350
351        # Give tests the default manifest on Windows (a no-op elsewhere).
352        "//build/win:default_exe_manifest",
353      ]
354    }
355
356    # TODO(GYP_GONE): Delete this after we've converted everything to GN.
357    # The _run targets exist only for compatibility with GYP.
358    group("${target_name}_run") {
359      testonly = true
360      deps = [
361        ":${invoker.target_name}",
362      ]
363    }
364
365    if (defined(invoker.output_name) && target_name != invoker.output_name) {
366      group("${invoker.output_name}_run") {
367        testonly = true
368        deps = [
369          ":${invoker.target_name}",
370        ]
371      }
372    }
373  }
374}
375