1# Copyright 2015 The Chromium Authors 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 9import("//build/config/chromeos/args.gni") 10import("//build/config/chromeos/ui_mode.gni") 11import("//build/config/devtools.gni") 12import("//build/config/gclient_args.gni") 13import("//build/rust/rust_static_library.gni") 14import("//build_overrides/build.gni") 15 16declare_args() { 17 # Some component repos (e.g. ANGLE) import //testing but do not have 18 # "location_tags.json", and so we don't want to try and upload the tags 19 # for their tests. 20 # And, some build configs may simply turn off generation altogether. 21 tests_have_location_tags = generate_location_tags 22} 23 24# On Fuchsia, the test executable has a suffix and is a dependency of the 25# common |target_name| target. For `visibility`, the executable must be 26# specified. Cross-platform targets that include `test` targets in their 27# visibility lists, add `${exec_target_suffix}` immediately after the test 28# target name. This is not necessary when the target is a `source_set`. 29if (is_fuchsia) { 30 exec_target_suffix = "__exec" 31} else { 32 exec_target_suffix = "" 33} 34 35if (is_android) { 36 import("//build/config/android/config.gni") 37 import("//build/config/android/create_unwind_table.gni") 38 import("//build/config/android/extract_unwind_tables.gni") 39 import("//build/config/android/rules.gni") 40 import("//build/config/sanitizers/sanitizers.gni") 41} else if (is_fuchsia) { 42 import("//build/config/cast.gni") 43 import("//build/config/fuchsia/generate_runner_scripts.gni") 44 import("//third_party/fuchsia-gn-sdk/src/cmc.gni") 45 import("//third_party/fuchsia-gn-sdk/src/component.gni") 46 import("//third_party/fuchsia-gn-sdk/src/package.gni") 47} else if (is_chromeos && is_chromeos_device) { 48 import("//build/config/chromeos/rules.gni") 49 import("//build/config/sanitizers/sanitizers.gni") 50 import("//build/util/generate_wrapper.gni") 51} else if (is_ios) { 52 import("//build/config/ios/ios_sdk.gni") 53 import("//build/config/ios/ios_test_runner_wrapper.gni") 54 import("//build/config/ios/rules.gni") 55} else { 56 import("//build/config/sanitizers/sanitizers.gni") 57 import("//build/util/generate_wrapper.gni") 58} 59 60# This template generates the test target (of type `target_type`) but also 61# generates a rust library that includes all .rs files found in sources and 62# depends on that from the test target. 63template("mixed_test") { 64 assert(defined(invoker.target_type) && invoker.target_type != "") 65 66 # The crate_root variable would transform the target into a Rust binary 67 # which is incorrect. To not use a generated crate root set: 68 # ``` 69 # test_crate_root = "path/to/root.rs" 70 # ``` 71 assert(!defined(invoker.crate_root)) 72 73 _rs_vars = [ 74 "sources", # We split this list into two. 75 "crate_name", # Android test template overrides the crate name. 76 ] 77 78 if (defined(invoker.sources)) { 79 _rs_sources = filter_include(invoker.sources, [ "*.rs" ]) 80 _cc_sources = filter_exclude(invoker.sources, [ "*.rs" ]) 81 } else { 82 _rs_sources = [] 83 _cc_sources = [] 84 } 85 86 if (_rs_sources != []) { 87 # Note: as a weak convention, __ is usually used before a suffix for 88 # internally-generated targets. However, rust_target requires a strict 89 # snake_case name. 90 if (defined(invoker.crate_name)) { 91 _rust_target_name = "${invoker.crate_name}_rust_objects" 92 } else { 93 _rust_target_name = "${target_name}_rust_objects" 94 } 95 96 # We could automatically add `deps += [ "//testing/rust_gtest_interop" ]` 97 # if `rs_sources` is non-empty. But we don't automatically provide 98 # //testing/gtest either so it would be asymmetric and could break in that 99 # case. So, we act instead as if //testing/rust_gtest_interop is part of 100 # the //testing/gtest dependency. If you add one, and have `rs_sources` 101 # listed, you get both. 102 _gtest_is_in_deps = false 103 if (defined(invoker.deps) && invoker.deps != []) { 104 foreach(dep, invoker.deps) { 105 if (get_label_info(dep, "label_no_toolchain") == 106 "//testing/gtest:gtest") { 107 _gtest_is_in_deps = true 108 } 109 } 110 } 111 112 # TODO(danakj): This could be a rust_source_set perhaps, the point being 113 # that we need to link in all the .o object files inside the library, 114 # instead of dropping unreachable ones during linking (which would drop the 115 # tests). Alternatively we could use a special name suffix or other similar 116 # trick perhaps to ensure that all object files are linked in here. 117 rust_static_library(_rust_target_name) { 118 forward_variables_from(invoker, 119 TESTONLY_AND_VISIBILITY + [ 120 "allow_unsafe", 121 "deps", 122 "generate_crate_root", 123 "public_deps", 124 ]) 125 configs += [ "//build/rust:test" ] 126 if (defined(invoker.test_crate_root)) { 127 crate_root = invoker.test_crate_root 128 } else { 129 generate_crate_root = true 130 } 131 sources = _rs_sources 132 is_gtest_unittests = true 133 134 if (_gtest_is_in_deps) { 135 deps += [ "//testing/rust_gtest_interop" ] 136 } 137 } 138 } else { 139 not_needed(invoker, _rs_vars) 140 } 141 142 if (invoker.target_type == "shared_library_with_jni") { 143 # Needed for shared_library_with_jni. Keeping this import guarded so 144 # that projects who import //testing but not //third_party/jni_zero 145 # don't have issues. 146 import("//third_party/jni_zero/jni_zero.gni") 147 } 148 target(invoker.target_type, target_name) { 149 forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY + _rs_vars) 150 forward_variables_from(invoker, TESTONLY_AND_VISIBILITY) 151 sources = _cc_sources 152 if (!defined(deps)) { 153 deps = [] 154 } 155 if (!defined(ldflags)) { 156 ldflags = [] 157 } 158 159 if (_rs_sources != []) { 160 deps += [ ":${_rust_target_name}" ] 161 } 162 } 163} 164 165# Define a test as an executable (or apk on Android) with the "testonly" flag 166# set. 167# Variable: 168# use_xvfb: (optional) whether to run the executable under Xvfb. 169# use_raw_android_executable: Use executable() rather than android_apk(). 170# use_native_activity: Test implements ANativeActivity_onCreate(). 171# test_runner_shard: (Fuchsia, optional): for CFv2 tests, use the given test 172# runner shard rather than the default shard for the ELF runner when 173# assembling the test component. This is useful, for example, to use the 174# elf_test_ambient_exec_runner for tests that require 175# job_policy_ambient_mark_vmo_exec. 176# fuchsia_package_deps: (Fuchsia, optional) List of fuchsia_component() 177# targets that this test package contains. 178# is_xctest: (iOS, optional) whether to build the executable as XCTest. 179# Similar to the GN arg 'enable_run_ios_unittests_with_xctest' but 180# for build targets. 181# allow_cleartext_traffic: (Android, optional) whether to allow cleartext 182# network requests during the test. 183# enable_fuzztest: whether to allow the use of the FUZZ_TEST macro to 184# include fuzzing tests alongside unit tests. This introduces an 185# extra dependency and also creates additional metadata so that our 186# fuzzing infrastructure can find and run such tests. 187template("test") { 188 testonly = true 189 if (!is_ios) { 190 assert(!defined(invoker.is_xctest) || !invoker.is_xctest, 191 "is_xctest can be set only for iOS builds") 192 } 193 if (!is_android) { 194 assert(!defined(invoker.allow_cleartext_traffic), 195 "allow_cleartext_traffic can be set only for Android tests") 196 } 197 198 _fuzztest_deps = [] 199 if (defined(invoker.enable_fuzztest) && invoker.enable_fuzztest) { 200 _output_name = invoker.target_name 201 _fuzzer_options_target = "${_output_name}__fuzzer_options" 202 _fuzztest_deps = [ 203 ":${_fuzzer_options_target}", 204 "//third_party/fuzztest", 205 ] 206 207 # Generate minimal .options file so that ClusterFuzz knows to pass the 208 # -fuzz= argument. It's possible that in future we would want more 209 # fuzzing parameters to be configurable for FUZZ_TESTS, in which case 210 # perhaps we would want to abstract more of the logic from 211 # //testing/libfuzzer/fuzzer_test.gni. 212 config_file_name = _output_name + ".options" 213 action(_fuzzer_options_target) { 214 script = "//testing/libfuzzer/gen_fuzzer_config.py" 215 args = [ 216 "--config", 217 rebase_path("$root_build_dir/" + config_file_name, root_build_dir), 218 "--libfuzzer_options", 219 "fuzz=", 220 ] 221 outputs = [ "$root_build_dir/$config_file_name" ] 222 } 223 } 224 225 if (is_android) { 226 assert(!defined(invoker.use_xvfb) || !invoker.use_xvfb) 227 228 _use_default_launcher = 229 !defined(invoker.use_default_launcher) || invoker.use_default_launcher 230 if (!defined(invoker.use_raw_android_executable)) { 231 # Checkouts where build_with_chromium == false often have a custom GN 232 # template wrapper around test() which sets use_default_launcher == false. 233 # Set the _use_raw_android_executable default so that test() targets which 234 # do not use the custom wrapper 235 # (1) Do not cause "gn gen" to fail 236 # (2) Do not need to be moved into if(build_with_chromium) block. 237 _use_raw_android_executable = 238 !build_with_chromium && _use_default_launcher 239 } else { 240 not_needed([ "_use_default_launcher" ]) 241 _use_raw_android_executable = invoker.use_raw_android_executable 242 } 243 244 # output_name is used to allow targets with the same name but in different 245 # packages to still produce unique runner scripts. 246 _output_name = invoker.target_name 247 if (defined(invoker.output_name)) { 248 _output_name = invoker.output_name 249 } 250 251 _test_runner_target = "${_output_name}__test_runner_script" 252 _wrapper_script_vars = [ 253 "android_test_runner_script", 254 "ignore_all_data_deps", 255 "shard_timeout", 256 ] 257 258 assert(_use_raw_android_executable || enable_java_templates) 259 260 if (_use_raw_android_executable) { 261 not_needed(invoker, [ "add_unwind_tables_in_apk" ]) 262 263 _exec_target = "${target_name}__exec" 264 _dist_target = "${target_name}__dist" 265 _exec_output = 266 "$target_out_dir/${invoker.target_name}/${invoker.target_name}" 267 _crate_name = "${target_name}" 268 269 mixed_test(_exec_target) { 270 target_type = "executable" 271 272 # Use a crate name that avoids creating a warning due to double 273 # underscore (ie. `__`). 274 crate_name = _crate_name 275 276 # Configs will always be defined since we set_defaults in 277 # BUILDCONFIG.gn. 278 configs = [] 279 forward_variables_from( 280 invoker, 281 "*", 282 TESTONLY_AND_VISIBILITY + _wrapper_script_vars + [ 283 "data_deps", 284 "extra_dist_files", 285 ]) 286 287 # Thanks to the set_defaults() for test(), configs are initialized with 288 # the default shared_library configs rather than executable configs. 289 configs -= [ 290 "//build/config:shared_library_config", 291 "//build/config/android:hide_all_but_jni", 292 ] 293 configs += [ "//build/config:executable_config" ] 294 295 if (defined(invoker.data_deps)) { 296 data_deps = invoker.data_deps 297 } else { 298 data_deps = [] 299 } 300 if (!defined(data)) { 301 data = [] 302 } 303 if (tests_have_location_tags) { 304 data += [ "//testing/location_tags.json" ] 305 } 306 if (!defined(deps)) { 307 deps = [] 308 } 309 deps += _fuzztest_deps 310 311 # Don't output to the root or else conflict with the group() below. 312 output_name = rebase_path(_exec_output, root_out_dir) 313 } 314 315 create_native_executable_dist(_dist_target) { 316 dist_dir = "$root_out_dir/$target_name" 317 binary = _exec_output 318 deps = [ ":$_exec_target" ] 319 if (defined(invoker.extra_dist_files)) { 320 extra_files = invoker.extra_dist_files 321 } 322 } 323 } else { 324 _library_target_name = "${target_name}__library" 325 _library_crate_name = "${target_name}_library" 326 _apk_target_name = "${target_name}__apk" 327 _apk_specific_vars = [ 328 "allow_cleartext_traffic", 329 "android_manifest", 330 "android_manifest_dep", 331 "android_manifest_template", 332 "app_as_shared_lib", 333 "product_config_java_packages", 334 "loadable_modules", 335 "loadable_module_deps", 336 "min_sdk_version", 337 "proguard_configs", 338 "proguard_enabled", 339 "srcjar_deps", 340 "target_sdk_version", 341 "use_default_launcher", 342 "use_native_activity", 343 ] 344 345 _add_unwind_tables_in_apk = 346 defined(invoker.add_unwind_tables_in_apk) && 347 invoker.add_unwind_tables_in_apk && target_cpu == "arm" 348 349 # Adds the unwind tables from unstripped binary as an asset file in the 350 # apk, if |add_unwind_tables_in_apk| is specified by the test. 351 if (_add_unwind_tables_in_apk) { 352 # TODO(crbug.com/1315603): Remove generation of v1 unwind asset when 353 # `CFIBacktraceAndroid` is replaced with `ChromeUnwinderAndroid`. 354 _unwind_table_name = "${_library_target_name}_unwind_v1" 355 unwind_table_v1(_unwind_table_name) { 356 library_target = ":$_library_target_name" 357 } 358 359 if (use_android_unwinder_v2) { 360 _unwind_table_v2_name = "${_library_target_name}_unwind_v2" 361 unwind_table_v2(_unwind_table_v2_name) { 362 library_target = ":$_library_target_name" 363 } 364 } 365 366 _unwind_table_asset_name = "${target_name}__unwind_assets" 367 android_assets(_unwind_table_asset_name) { 368 sources = [ "$target_out_dir/$_unwind_table_name/$unwind_table_asset_v1_filename" ] 369 disable_compression = true 370 deps = [ ":$_unwind_table_name" ] 371 if (use_android_unwinder_v2) { 372 sources += [ "$target_out_dir/$_unwind_table_v2_name/$unwind_table_asset_v2_filename" ] 373 deps += [ ":$_unwind_table_v2_name" ] 374 } 375 } 376 } 377 378 _generate_final_jni = 379 !defined(invoker.generate_final_jni) || invoker.generate_final_jni 380 mixed_test(_library_target_name) { 381 if (_generate_final_jni) { 382 target_type = "shared_library_with_jni" 383 java_targets = [ ":$_apk_target_name" ] 384 } else { 385 target_type = "shared_library" 386 } 387 388 # Configs will always be defined since we set_defaults in 389 # BUILDCONFIG.gn. 390 configs = [] # Prevent list overwriting warning. 391 configs = invoker.configs 392 393 forward_variables_from( 394 invoker, 395 "*", 396 [ 397 "configs", 398 "deps", 399 ] + _apk_specific_vars + _wrapper_script_vars + 400 TESTONLY_AND_VISIBILITY) 401 402 # Use a crate name that avoids creating a warning due to double 403 # underscore (ie. `__`). 404 crate_name = _library_crate_name 405 406 # Native targets do not need to depend on java targets. Filter them out 407 # so that the shared library can be built without needing to wait for 408 # dependent java targets. 409 deps = _fuzztest_deps 410 if (defined(invoker.deps)) { 411 deps += filter_exclude(invoker.deps, java_target_patterns) 412 } 413 414 if (_use_default_launcher) { 415 deps += [ "//testing/android/native_test:native_test_native_code" ] 416 } 417 } 418 unittest_apk(_apk_target_name) { 419 forward_variables_from(invoker, _apk_specific_vars) 420 shared_library = ":$_library_target_name" 421 if (_generate_final_jni) { 422 srcjar_deps = [ "${shared_library}__jni_registration" ] 423 } 424 apk_name = invoker.target_name 425 if (defined(invoker.output_name)) { 426 apk_name = invoker.output_name 427 } 428 429 if (defined(invoker.deps)) { 430 deps = invoker.deps 431 } else { 432 deps = [] 433 } 434 if (defined(loadable_module_deps)) { 435 deps += loadable_module_deps 436 } 437 438 # Add the Java classes so that each target does not have to do it. 439 if (_use_default_launcher) { 440 deps += [ "//base/test:test_support_java" ] 441 } 442 443 if (defined(_unwind_table_asset_name)) { 444 deps += [ ":${_unwind_table_asset_name}" ] 445 } 446 } 447 } 448 449 test_runner_script(_test_runner_target) { 450 forward_variables_from(invoker, _wrapper_script_vars) 451 452 if (_use_raw_android_executable) { 453 executable_dist_dir = "$root_out_dir/$_dist_target" 454 data_deps = [ ":$_exec_target" ] 455 } else { 456 apk_target = ":$_apk_target_name" 457 incremental_apk = incremental_install 458 459 # Dep needed for the test runner .runtime_deps file to pick up data 460 # deps from the forward_variables_from(invoker, "*") on the library. 461 data_deps = [ ":$_library_target_name" ] 462 } 463 test_name = _output_name 464 test_suite = _output_name 465 test_type = "gtest" 466 } 467 468 # Create a wrapper script rather than using a group() in order to ensure 469 # "ninja $target_name" always works. If this was a group(), then GN would 470 # not create a top-level alias for it if a target exists in another 471 # directory with the same $target_name. 472 # Also - bots run this script directly for "components_perftests". 473 generate_wrapper(target_name) { 474 forward_variables_from(invoker, [ "visibility" ]) 475 executable = "$root_build_dir/bin/run_$_output_name" 476 wrapper_script = "$root_build_dir/$_output_name" 477 deps = [ ":$_test_runner_target" ] 478 if (_use_raw_android_executable) { 479 deps += [ ":$_dist_target" ] 480 } else { 481 # Dep needed for the swarming .isolate file to pick up data 482 # deps from the forward_variables_from(invoker, "*") on the library. 483 deps += [ 484 ":$_apk_target_name", 485 ":$_library_target_name", 486 ] 487 } 488 489 if (defined(invoker.data_deps)) { 490 data_deps = invoker.data_deps 491 } else { 492 data_deps = [] 493 } 494 495 data_deps += [ "//testing:test_scripts_shared" ] 496 497 if (tests_have_location_tags) { 498 data = [ "//testing/location_tags.json" ] 499 } 500 } 501 } else if (is_fuchsia) { 502 assert(!defined(invoker.use_xvfb) || !invoker.use_xvfb) 503 504 _output_name = invoker.target_name 505 _pkg_target = "${_output_name}_pkg" 506 _exec_target = "${_output_name}__exec" 507 _program_name = get_label_info(":${_exec_target}", "name") 508 _crate_name = _output_name 509 510 # Generate a CML fragment that provides the program name. 511 _test_program_fragment_target = "${target_name}_program-fragment" 512 _test_program_fragment = "${target_out_dir}/${target_name}_program.test-cml" 513 generated_file(_test_program_fragment_target) { 514 contents = { 515 program = { 516 binary = _program_name 517 } 518 } 519 outputs = [ _test_program_fragment ] 520 output_conversion = "json" 521 } 522 523 _test_runner_shard = 524 "//build/config/fuchsia/test/elf_test_runner.shard.test-cml" 525 if (defined(invoker.test_runner_shard)) { 526 _test_runner_shard = invoker.test_runner_shard 527 } 528 529 # Collate the complete set of elements to include in the test component's 530 # manifest. 531 532 _manifest_fragments = [ 533 _test_program_fragment, 534 _test_runner_shard, 535 ] 536 537 # Select the Fuchsia test realm in which to run the test. 538 if (defined(invoker.run_as_chromium_system_test) && 539 invoker.run_as_chromium_system_test) { 540 _manifest_fragments += [ 541 "//build/config/fuchsia/test/chromium_system_test_facet.shard.test-cml", 542 "//build/config/fuchsia/test/system_test_minimum.shard.test-cml", 543 ] 544 } else { 545 _manifest_fragments += [ 546 "//build/config/fuchsia/test/chromium_test_facet.shard.test-cml", 547 "//build/config/fuchsia/test/minimum.shard.test-cml", 548 ] 549 } 550 551 if (is_asan) { 552 # TODO(crbug.com/1465997): Remove the extra cml segment for asan. 553 _manifest_fragments += 554 [ "//build/config/fuchsia/test/asan_options.shard.test-cml" ] 555 } 556 557 _test_component_manifest = "${target_out_dir}/${target_name}.cml" 558 _merged_manifest_name = "${_output_name}.cml" 559 560 if (defined(invoker.additional_manifest_fragments)) { 561 _manifest_fragments += invoker.additional_manifest_fragments 562 } 563 564 # Generate the test component manifest from the specified elements. 565 _test_component_manifest_target = "${target_name}_component-manifest" 566 cmc_merge(_test_component_manifest_target) { 567 sources = _manifest_fragments 568 output_name = "${_merged_manifest_name}" 569 deps = [ ":${_test_program_fragment_target}" ] 570 } 571 572 # Define the test component, dependent on the generated manifest, and the 573 # test executable target. 574 _test_component_target = "${target_name}_component" 575 fuchsia_component(_test_component_target) { 576 deps = [ ":$_test_component_manifest_target" ] 577 data_deps = [ ":$_exec_target" ] 578 manifest = _test_component_manifest 579 visibility = [ ":*" ] 580 } 581 582 _test_component_targets = [ ":${_test_component_target}" ] 583 584 # Define components for each entry in |additional_manifests|, if any. Since 585 # manifests may themselves depend-on the outputs of |deps|, these components 586 # must each individually depend on |invoker.deps|. 587 if (defined(invoker.additional_manifests)) { 588 foreach(filename, invoker.additional_manifests) { 589 _additional_component_target = 590 target_name + "_" + get_path_info(filename, "name") 591 _test_component_targets += [ ":${_additional_component_target}" ] 592 fuchsia_component(_additional_component_target) { 593 forward_variables_from(invoker, [ "testonly" ]) 594 data_deps = [ ":$_exec_target" ] 595 visibility = [ ":*" ] 596 manifest = filename 597 598 # Depend on |invoker.deps|, in case it includes a dependency that 599 # creates this additional component's manifest. 600 if (defined(invoker.deps)) { 601 deps = invoker.deps 602 } 603 } 604 } 605 } 606 607 # Define the package target that will bundle the test and additional 608 # components and their data. 609 fuchsia_package(_pkg_target) { 610 forward_variables_from(invoker, 611 [ 612 "excluded_files", 613 "excluded_dirs", 614 "excluded_paths", 615 ]) 616 package_name = _output_name 617 deps = _test_component_targets 618 619 if (defined(invoker.fuchsia_package_deps)) { 620 deps += invoker.fuchsia_package_deps 621 } 622 if (!defined(excluded_paths)) { 623 excluded_paths = [] 624 } 625 excluded_paths += [ 626 "${devtools_root_location}/*", 627 "*.git/*", 628 "*.svn/*", 629 "*.hg/*", 630 ] 631 if (devtools_root_location != "") { 632 excluded_paths += [ "${devtools_root_location}/*" ] 633 } 634 } 635 636 # |target_name| refers to the package-runner rule, so that building 637 # "base_unittests" will build not only the executable, component, and 638 # package, but also the script required to run them. 639 fuchsia_test_runner(target_name) { 640 forward_variables_from(invoker, 641 [ 642 "data", 643 "data_deps", 644 "package_deps", 645 "use_test_server", 646 ]) 647 648 is_test_exe = true 649 package = ":$_pkg_target" 650 package_name = _output_name 651 652 if (!defined(deps)) { 653 deps = [] 654 } 655 if (defined(invoker.deps)) { 656 deps += invoker.deps 657 } 658 659 if (!defined(data)) { 660 data = [] 661 } 662 if (tests_have_location_tags) { 663 data += [ "//testing/location_tags.json" ] 664 } 665 666 if (!defined(data_deps)) { 667 data_deps = [] 668 } 669 670 data_deps += [ "//testing:test_scripts_shared" ] 671 } 672 673 mixed_test(_exec_target) { 674 target_type = "executable" 675 forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) 676 output_name = _exec_target 677 678 if (!defined(deps)) { 679 deps = [] 680 } 681 deps += _fuzztest_deps 682 683 # Use a crate name that avoids creating a warning due to double 684 # underscore (ie. `__`). 685 crate_name = _crate_name 686 } 687 } else if (is_ios) { 688 assert(!defined(invoker.use_xvfb) || !invoker.use_xvfb) 689 _runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps" 690 691 declare_args() { 692 # Keep the unittest-as-xctest functionality defaulted to off for 693 # local builds and test executions. 694 enable_run_ios_unittests_with_xctest = false 695 } 696 697 _test_target = target_name 698 699 _wrapper_output_name = "run_${target_name}" 700 ios_test_runner_wrapper(_wrapper_output_name) { 701 forward_variables_from(invoker, 702 [ 703 "clones", 704 "data", 705 "deps", 706 "executable_args", 707 "retries", 708 709 # TODO(crbug.com/1500395) deprecate shards 710 "shards", 711 ]) 712 713 _root_build_dir = rebase_path("${root_build_dir}", root_build_dir) 714 715 if (!defined(executable_args)) { 716 executable_args = [] 717 } 718 executable_args += [ 719 "--app", 720 "@WrappedPath(${_root_build_dir}/${_test_target}.app)", 721 ] 722 723 wrapper_output_name = "${_wrapper_output_name}" 724 725 if (!defined(data)) { 726 data = [] 727 } 728 if (tests_have_location_tags) { 729 data += [ "//testing/location_tags.json" ] 730 } 731 } 732 733 _resources_bundle_data = target_name + "_resources_bundle_data" 734 735 bundle_data(_resources_bundle_data) { 736 visibility = [ ":$_test_target" ] 737 sources = [ "//testing/gtest_ios/Default.png" ] 738 outputs = [ "{{bundle_resources_dir}}/{{source_file_part}}" ] 739 } 740 741 force_xctest = enable_run_ios_unittests_with_xctest || 742 (defined(invoker.is_xctest) && invoker.is_xctest) 743 744 mixed_test(_test_target) { 745 if (force_xctest) { 746 target_type = "ios_xctest_test" 747 } else { 748 target_type = "ios_app_bundle" 749 } 750 testonly = true 751 752 if (force_xctest && build_with_chromium) { 753 xctest_module_target = "//base/test:google_test_runner" 754 } 755 756 forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) 757 758 # Provide sensible defaults in case invoker did not define any of those 759 # required variables. 760 if (!defined(info_plist) && !defined(info_plist_target)) { 761 info_plist = "//testing/gtest_ios/unittest-Info.plist" 762 } 763 764 bundle_identifier = shared_bundle_id_for_test_apps 765 766 if (!defined(bundle_deps)) { 767 bundle_deps = [] 768 } 769 bundle_deps += [ ":$_resources_bundle_data" ] 770 771 if (!defined(data_deps)) { 772 data_deps = [] 773 } 774 775 data_deps += [ "//testing:test_scripts_shared" ] 776 777 # Include the generate_wrapper as part of data_deps 778 data_deps += [ ":${_wrapper_output_name}" ] 779 write_runtime_deps = _runtime_deps_file 780 if (!defined(deps)) { 781 deps = [] 782 } 783 deps += _fuzztest_deps 784 } 785 } else if ((is_chromeos_ash || (is_chromeos_lacros && is_chromeos_device)) && 786 cros_board != "") { 787 assert(!defined(invoker.use_xvfb) || !invoker.use_xvfb) 788 789 # Building for a cros board (ie: not linux-chromeos or linux-lacros). 790 791 _gen_runner_target = "${target_name}__runner" 792 _runtime_deps_file = 793 "$root_out_dir/gen.runtime/" + get_label_info(target_name, "dir") + 794 "/" + get_label_info(target_name, "name") + ".runtime_deps" 795 796 if (is_skylab && (defined(tast_attr_expr) || defined(tast_tests) || 797 defined(tast_disabled_tests))) { 798 generate_skylab_tast_filter(_gen_runner_target) { 799 } 800 } else { 801 generate_runner_script(_gen_runner_target) { 802 generated_script = "$root_build_dir/bin/run_" + invoker.target_name 803 test_exe = invoker.target_name 804 runtime_deps_file = _runtime_deps_file 805 806 if (is_chromeos_lacros) { 807 # At build time, Lacros tests don't know whether they'll run on VM or 808 # HW, and instead, these flags are specified at runtime when invoking 809 # the generated runner script. 810 skip_generating_board_args = true 811 } 812 813 if (tests_have_location_tags) { 814 data = [ "//testing/location_tags.json" ] 815 } 816 } 817 } 818 819 mixed_test(target_name) { 820 target_type = "executable" 821 forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) 822 forward_variables_from(invoker, [ "visibility" ]) 823 if (!defined(deps)) { 824 deps = [] 825 } 826 if (!defined(data)) { 827 data = [] 828 } 829 830 # We use a special trigger script for CrOS hardware tests. 831 data += [ "//testing/trigger_scripts/chromeos_device_trigger.py" ] 832 833 write_runtime_deps = _runtime_deps_file 834 data += [ _runtime_deps_file ] 835 deps += [ ":$_gen_runner_target" ] 836 deps += _fuzztest_deps 837 838 if (!defined(data_deps)) { 839 data_deps = [] 840 } 841 842 data_deps += [ "//testing:test_scripts_shared" ] 843 } 844 } else if (is_chromeos_lacros && !is_chromeos_device) { 845 _runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps" 846 _executable = target_name 847 _gen_runner_target = "${target_name}__runner" 848 849 if (defined(invoker.use_xvfb)) { 850 _use_xvfb = invoker.use_xvfb 851 } else { 852 _use_xvfb = false 853 } 854 855 # When use_xvfb is set by the invoker, it indicates that running this test 856 # target requires a window, and in lacros build, ash-chrome serves as the 857 # display server. Note that even though the tests themselves do not require 858 # xvfb anymore, xvfb.py is still needed to invoke the lacros test runner 859 # because ash-chrome is based on x11. 860 _use_ash_chrome = _use_xvfb 861 862 generate_wrapper(_gen_runner_target) { 863 wrapper_script = "$root_build_dir/bin/run_" + _executable 864 865 data = [] 866 data_deps = [ "//testing:test_scripts_shared" ] 867 868 if (_use_xvfb) { 869 executable = "//testing/xvfb.py" 870 data += [ "//.vpython3" ] 871 } else { 872 executable = "//testing/test_env.py" 873 } 874 if (tests_have_location_tags) { 875 data += [ "//testing/location_tags.json" ] 876 } 877 878 executable_args = [ 879 "@WrappedPath(../../build/lacros/test_runner.py)", 880 "test", 881 "@WrappedPath(./${_executable})", 882 "--test-launcher-bot-mode", 883 ] 884 885 if (_use_ash_chrome) { 886 executable_args += [ "--ash-chrome-path" ] 887 888 # Can't use --ash-chrome-path=path because WrappedPath 889 # won't be expanded for that usage. 890 executable_args += [ "@WrappedPath(./ash_clang_x64/test_ash_chrome)" ] 891 } 892 893 if (is_asan) { 894 executable_args += [ "--asan=1" ] 895 } 896 if (is_msan) { 897 executable_args += [ "--msan=1" ] 898 } 899 if (is_tsan) { 900 executable_args += [ "--tsan=1" ] 901 } 902 if (use_cfi_diag) { 903 executable_args += [ "--cfi-diag=1" ] 904 } 905 if (fail_on_san_warnings) { 906 executable_args += [ "--fail-san=1" ] 907 } 908 909 data += [ "//build/lacros/test_runner.py" ] 910 } 911 912 mixed_test(target_name) { 913 target_type = "executable" 914 forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) 915 forward_variables_from(invoker, [ "visibility" ]) 916 if (!defined(deps)) { 917 deps = [] 918 } 919 920 if (!defined(data_deps)) { 921 data_deps = [] 922 } 923 924 data_deps += [ "//testing:test_scripts_shared" ] 925 926 write_runtime_deps = _runtime_deps_file 927 deps += [ ":$_gen_runner_target" ] 928 deps += _fuzztest_deps 929 if (_use_ash_chrome && also_build_ash_chrome) { 930 data_deps += [ "//chrome/test:test_ash_chrome(//build/toolchain/linux:ash_clang_x64)" ] 931 } 932 } 933 } else if (!is_nacl) { 934 if (is_mac || is_win) { 935 assert(!defined(invoker.use_xvfb) || !invoker.use_xvfb) 936 } 937 938 _runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps" 939 _executable = target_name 940 _gen_runner_target = "${target_name}__runner" 941 942 if ((is_linux || is_chromeos) && defined(invoker.use_xvfb)) { 943 _use_xvfb = invoker.use_xvfb 944 } else { 945 _use_xvfb = false 946 } 947 948 generate_wrapper(_gen_runner_target) { 949 wrapper_script = "$root_build_dir/bin/run_" + _executable 950 951 data = [] 952 data_deps = [ "//testing:test_scripts_shared" ] 953 954 if (_use_xvfb) { 955 executable = "//testing/xvfb.py" 956 } else { 957 executable = "//testing/test_env.py" 958 } 959 if (tests_have_location_tags) { 960 data += [ "//testing/location_tags.json" ] 961 } 962 963 executable_args = [ 964 "@WrappedPath(./${_executable})", 965 "--test-launcher-bot-mode", 966 ] 967 if (is_asan) { 968 executable_args += [ "--asan=1" ] 969 } 970 if (is_msan) { 971 executable_args += [ "--msan=1" ] 972 } 973 if (is_tsan) { 974 executable_args += [ "--tsan=1" ] 975 } 976 if (use_cfi_diag) { 977 executable_args += [ "--cfi-diag=1" ] 978 } 979 if (fail_on_san_warnings) { 980 executable_args += [ "--fail-san=1" ] 981 } 982 } 983 984 mixed_test(target_name) { 985 target_type = "executable" 986 forward_variables_from(invoker, 987 "*", 988 TESTONLY_AND_VISIBILITY + [ "use_xvfb" ]) 989 forward_variables_from(invoker, [ "visibility" ]) 990 if (!defined(deps)) { 991 deps = [] 992 } 993 994 deps += [ 995 # Give tests the default manifest on Windows (a no-op elsewhere). 996 "//build/win:default_exe_manifest", 997 ] 998 999 write_runtime_deps = _runtime_deps_file 1000 deps += [ ":$_gen_runner_target" ] 1001 deps += _fuzztest_deps 1002 1003 if (!defined(data_deps)) { 1004 data_deps = [] 1005 } 1006 1007 data_deps += [ "//testing:test_scripts_shared" ] 1008 } 1009 } else { 1010 # This is a catch-all clause for NaCl toolchains and other random 1011 # configurations that might define tests; test() in these configs 1012 # will just define the underlying executables. 1013 assert(!defined(invoker.use_xvfb) || !invoker.use_xvfb, 1014 "use_xvfb should not be defined for a non-linux configuration") 1015 mixed_test(target_name) { 1016 target_type = "executable" 1017 forward_variables_from(invoker, "*", TESTONLY_AND_VISIBILITY) 1018 forward_variables_from(invoker, [ "visibility" ]) 1019 if (!defined(deps)) { 1020 deps = [] 1021 } 1022 deps += _fuzztest_deps 1023 1024 if (!defined(data_deps)) { 1025 data_deps = [] 1026 } 1027 1028 data_deps += [ "//testing:test_scripts_shared" ] 1029 } 1030 } 1031} 1032 1033# Defines a type of test that invokes a script to run, rather than 1034# invoking an executable. 1035# 1036# The script must implement the 1037# [test executable API](//docs/testing/test_executable_api.md). 1038# 1039# The template must be passed the `script` parameter, which specifies the path 1040# to the script to run. It may optionally be passed a `args` parameter, which 1041# can be used to include a list of args to be specified by default. The 1042# template will produce a `$root_build_dir/run_$target_name` wrapper and write 1043# the runtime_deps for the target to 1044# $root_build_dir/${target_name}.runtime_deps, as per the conventions listed in 1045# the [test wrapper API](//docs/testing/test_wrapper_api.md). 1046template("script_test") { 1047 generate_wrapper(target_name) { 1048 testonly = true 1049 wrapper_script = "${root_build_dir}/bin/run_${target_name}" 1050 1051 executable = "//testing/test_env.py" 1052 1053 executable_args = 1054 [ "@WrappedPath(" + rebase_path(invoker.script, root_build_dir) + ")" ] 1055 if (defined(invoker.args)) { 1056 executable_args += invoker.args 1057 } 1058 1059 data = [ invoker.script ] 1060 1061 if (defined(invoker.data)) { 1062 data += invoker.data 1063 } 1064 if (tests_have_location_tags) { 1065 data += [ "//testing/location_tags.json" ] 1066 } 1067 1068 data_deps = [ "//testing:test_scripts_shared" ] 1069 if (defined(invoker.data_deps)) { 1070 data_deps += invoker.data_deps 1071 } 1072 1073 forward_variables_from(invoker, 1074 "*", 1075 TESTONLY_AND_VISIBILITY + [ 1076 "args", 1077 "data", 1078 "data_deps", 1079 "script", 1080 ]) 1081 forward_variables_from(invoker, [ "visibility" ]) 1082 1083 write_runtime_deps = "${root_build_dir}/${target_name}.runtime_deps" 1084 } 1085} 1086 1087# Defines a test target that uses exit code for pass/fail. 1088template("isolated_script_test") { 1089 script_test(target_name) { 1090 forward_variables_from(invoker, 1091 "*", 1092 TESTONLY_AND_VISIBILITY + [ 1093 "args", 1094 "deps", 1095 "script", 1096 ]) 1097 forward_variables_from(invoker, [ "visibility" ]) 1098 deps = [ "//testing:run_isolated_script_test" ] 1099 if (defined(invoker.deps)) { 1100 deps += invoker.deps 1101 } 1102 script = "//testing/scripts/run_isolated_script_test.py" 1103 data = [ invoker.script ] 1104 args = [ 1105 rebase_path(invoker.script, root_build_dir), 1106 "--script-type=bare", 1107 ] 1108 if (defined(invoker.args)) { 1109 args += invoker.args 1110 } 1111 } 1112} 1113 1114# Test defaults. 1115set_defaults("test") { 1116 if (is_android) { 1117 configs = default_shared_library_configs 1118 configs -= [ "//build/config/android:hide_all_but_jni_onload" ] 1119 configs += [ "//build/config/android:hide_all_but_jni" ] 1120 1121 # Compress sections to stay under 4gb hard limit on 32-bit current_cpu. 1122 # https://crbug.com/1354616 1123 if (symbol_level == 2 && !use_debug_fission && 1124 (current_cpu == "arm" || current_cpu == "x86")) { 1125 configs += [ "//build/config:compress_debug_sections" ] 1126 } 1127 } else { 1128 configs = default_executable_configs 1129 } 1130} 1131