1# Copyright 2018 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 5import("//build/config/chrome_build.gni") 6import("//build/config/chromeos/args.gni") 7import("//build/config/chromeos/ui_mode.gni") 8import("//build/config/dcheck_always_on.gni") 9import("//build/config/gclient_args.gni") 10import("//build/config/python.gni") 11import("//build/util/generate_wrapper.gni") 12 13assert(is_chromeos) 14assert(is_chromeos_device) 15 16# Determine the real paths for various items in the SDK, which may be used 17# in the 'generate_runner_script' template below. We do so outside the template 18# to confine exec_script to a single invocation. 19if (cros_sdk_version != "") { 20 # Ideally these should be maps, however, gn doesn't support map, so using a 21 # list of list to simulate a map: 22 # [key1, [value1, value2, ...]], [key2, [value1, value2, ...]], where 23 # the keys are boards and values are symlinks or symlink targets, and the 24 # mapping shouldn't be used for anything else. 25 # 26 # A sample usage is: 27 # foreach(m, _symlink_targets_map) { 28 # if(m[0] == target_key) { 29 # target_value = m[1] 30 # } 31 # } 32 # 33 _symlink_map = [] 34 _symlink_targets_map = [] 35 36 if (is_chromeos_ash) { 37 _potential_test_boards = [ cros_board ] 38 } else { 39 _potential_test_boards = [] 40 if (cros_boards != "") { 41 _potential_test_boards += string_split(cros_boards, ":") 42 } 43 if (cros_boards_with_qemu_images != "") { 44 _potential_test_boards += string_split(cros_boards_with_qemu_images, ":") 45 } 46 } 47 48 foreach(b, _potential_test_boards) { 49 _cache_path_prefix = 50 "//build/cros_cache/chrome-sdk/symlinks/${b}+${cros_sdk_version}" 51 52 _cros_is_vm = false 53 foreach(b1, string_split(cros_boards_with_qemu_images, ":")) { 54 if (b == b1) { 55 _cros_is_vm = true 56 } 57 } 58 59 _symlinks = [] 60 _symlinks = [ 61 # Tast harness & test data. 62 rebase_path("${_cache_path_prefix}+autotest_server_package.tar.bz2"), 63 64 # Binutils (and other toolchain tools) used to deploy Chrome to the device. 65 rebase_path( 66 "${_cache_path_prefix}+environment_chromeos-base_chromeos-chrome.tar.xz"), 67 rebase_path("${_cache_path_prefix}+target_toolchain"), 68 ] 69 if (_cros_is_vm) { 70 # VM-related tools. 71 _symlinks += 72 [ rebase_path("${_cache_path_prefix}+chromiumos_test_image.tar.xz") ] 73 } 74 _symlink_map += [ [ 75 b, 76 _symlinks, 77 ] ] 78 } 79 80 _all_symlinks = [] 81 foreach(m, _symlink_map) { 82 _all_symlinks += m[1] 83 } 84 _all_symlink_targets = 85 exec_script("//build/get_symlink_targets.py", _all_symlinks, "list lines") 86 _index = 0 87 foreach(m, _symlink_map) { 88 _symlink_targets = [] 89 foreach(_, m[1]) { 90 _symlink_targets += [ _all_symlink_targets[_index] ] 91 _index += 1 92 } 93 94 _symlink_targets_map += [ [ 95 m[0], 96 _symlink_targets, 97 ] ] 98 } 99} 100 101template("generate_chromeos_sdk_deps") { 102 forward_variables_from(invoker, 103 [ 104 "deploy_chrome", 105 "is_tast", 106 ]) 107 if (!defined(deploy_chrome)) { 108 deploy_chrome = false 109 } 110 if (!defined(is_tast)) { 111 is_tast = false 112 } 113 114 _sdk_data = [] 115 assert(cros_sdk_version != "", "cros sdk version is not defined") 116 foreach(b, _potential_test_boards) { 117 _cros_is_vm = false 118 foreach(b1, string_split(cros_boards_with_qemu_images, ":")) { 119 if (b == b1) { 120 _cros_is_vm = true 121 } 122 } 123 124 # Determine the real paths for various items in the SDK, which may be used 125 # in the 'generate_runner_script' template below. 126 if (is_tast || _cros_is_vm || deploy_chrome) { 127 _symlink_targets = [] 128 foreach(m, _symlink_targets_map) { 129 if (b == m[0]) { 130 _symlink_targets = [] 131 _symlink_targets = m[1] 132 } 133 } 134 135 if (is_tast) { 136 # Add tast sdk items. 137 _sdk_data += [ _symlink_targets[0] ] 138 } 139 if (deploy_chrome) { 140 # To deploy chrome to the VM, it needs to be stripped down to fit into 141 # the VM. This is done by using binutils in the toolchain. So add the 142 # toolchain to the data. 143 _sdk_data += [ 144 _symlink_targets[1], 145 _symlink_targets[2], 146 ] 147 } 148 if (_cros_is_vm) { 149 # Add vm sdk items. 150 _sdk_data += [ _symlink_targets[3] ] 151 } 152 } 153 } 154 group(target_name) { 155 data = _sdk_data 156 data += [ 157 # Needed for various SDK components used below. 158 "//build/cros_cache/chrome-sdk/misc/", 159 "//build/cros_cache/chrome-sdk/symlinks/", 160 "//chrome/VERSION", 161 162 # The LKGM file controls what version of the VM image to download. Add it 163 # as data here so that changes to it will trigger analyze. 164 "//chromeos/CHROMEOS_LKGM", 165 ] 166 if (cros_boards_with_qemu_images != "") { 167 data += [ "//build/cros_cache/cipd/" ] 168 } 169 } 170} 171 172# Creates tast filter files for skylab tast tests. 173# Args: 174# tast_attr_expr: Tast expression to determine tests to run. This creates the 175# initial set of tests that can be further filtered.. 176# tast_tests: Names of tests to enable in tast. All other tests will be 177# disabled that are not listed. 178# tast_disabled_tests: Names of tests to disable in tast. All other tests that 179# match the tast expression will still run. 180# tast_control: gni file with collections of tests to be used for specific 181# filters (e.g. "//chromeos/tast_control.gni"). Any lists of strings in 182# this file will be used to generate additional tast expressions with 183# those strings expanded into tests to disable (i.e. as && !"name:test"). 184# The name of those lists are then intended to be used to specify in 185# test_suites.pyl which collection to be used on specific test suites. 186template("generate_skylab_tast_filter") { 187 forward_variables_from(invoker, 188 [ 189 "tast_attr_expr", 190 "tast_tests", 191 "tast_disabled_tests", 192 "tast_control", 193 ]) 194 195 if (defined(tast_disabled_tests)) { 196 assert(defined(tast_attr_expr), 197 "tast_attr_expr must be used when specifying tast_disabled_tests.") 198 } 199 _generated_filter = "$root_build_dir/bin/${target_name}.filter" 200 _skylab_args = [ 201 "generate-filter", 202 "--output", 203 rebase_path(_generated_filter), 204 ] 205 if (defined(tast_control)) { 206 _skylab_args += [ 207 "--tast-control", 208 rebase_path(tast_control), 209 ] 210 } 211 if (defined(tast_attr_expr)) { 212 _skylab_args += [ 213 "--tast-expr", 214 tast_attr_expr, 215 ] 216 } 217 if (defined(tast_tests)) { 218 foreach(_test, tast_tests) { 219 _skylab_args += [ 220 "--enabled-tests", 221 _test, 222 ] 223 } 224 } 225 if (defined(tast_disabled_tests)) { 226 foreach(_test_name, tast_disabled_tests) { 227 _skylab_args += [ 228 "--disabled-tests", 229 _test_name, 230 ] 231 } 232 } 233 action(target_name) { 234 testonly = true 235 script = "//build/chromeos/generate_skylab_tast_filter.py" 236 if (defined(tast_control)) { 237 sources = [ tast_control ] 238 } 239 outputs = [ _generated_filter ] 240 args = _skylab_args 241 if (defined(invoker.data_deps)) { 242 data_deps = invoker.data_deps 243 } 244 data = [ _generated_filter ] 245 if (defined(invoker.data)) { 246 data += invoker.data 247 } 248 if (defined(invoker.deps)) { 249 deps = invoker.deps 250 } 251 } 252} 253 254# Creates a script at $generated_script that can be used to launch a cros VM 255# and optionally run a test within it. 256# Args: 257# test_exe: Name of test binary located in the out dir. This will get copied 258# to the VM and executed there. 259# tast_attr_expr: Tast expression to pass to local_test_runner on the VM. 260# tast_tests: List of Tast tests to run on the VM. Note that when this is 261# specified, the target name used to invoke this template will be 262# designated as the "name" of this test and will primarly used for test 263# results tracking and displaying (eg: flakiness dashboard). 264# generated_script: Path to place the generated script. 265# deploy_chrome: If true, deploys a locally built chrome located in the root 266# build dir to the VM or DUT after launching it. 267# deploy_lacros: If true, deploys a locally built Lacros located in the root 268# build dir to the VM or DUT after launching it. 269# runtime_deps_file: Path to file listing runtime deps for the test. If set, 270# all files listed will be copied to the VM before testing. 271# skip_generating_board_args: By default, this template generates an '--board' 272# arg with corresponding '--flash' or '--use-vm' args for device and vm 273# respectively. This argument instructs the template to skip generating 274# them, and it's designed for use cases where one builds for one board 275# (e.g. amd64-generic), but tests on a different board (e.g. eve). 276# tast_vars: A list of "key=value" runtime variable pairs to pass to invoke 277# strip_chrome: If true, strips Chrome before deploying it for non-Tast tests. 278# the Tast tests. For more details, please see: 279# https://chromium.googlesource.com/chromiumos/platform/tast/+/HEAD/docs/writing_tests.md#Runtime-variables 280template("generate_runner_script") { 281 forward_variables_from(invoker, 282 [ 283 "deploy_chrome", 284 "deploy_lacros", 285 "generated_script", 286 "runtime_deps_file", 287 "skip_generating_board_args", 288 "strip_chrome", 289 "tast_attr_expr", 290 "tast_tests", 291 "tast_vars", 292 "testonly", 293 "test_exe", 294 ]) 295 296 if (!defined(skip_generating_board_args)) { 297 # --board should be assigned by the autotest wrapper on skylab builders 298 skip_generating_board_args = is_skylab 299 } 300 301 if (skip_generating_board_args) { 302 # cros_board is not needed, so setting it to empty to avoid being used 303 # accidentally below. 304 cros_board = "" 305 not_needed([ cros_board ]) 306 } 307 308 if (!defined(deploy_chrome)) { 309 deploy_chrome = false 310 } 311 if (!defined(deploy_lacros)) { 312 deploy_lacros = false 313 } 314 if (!defined(strip_chrome)) { 315 strip_chrome = false 316 } 317 is_tast = defined(tast_attr_expr) || defined(tast_tests) 318 assert(!(is_tast && defined(test_exe)), 319 "Tast tests are invoked from binaries shipped with the VM image. " + 320 "There should be no locally built binary needed.") 321 assert(is_tast || !defined(tast_vars), 322 "tast_vars is only support for Tast tests") 323 324 if (is_tast) { 325 not_needed([ "strip_chrome" ]) 326 } 327 328 # If we're in the cros chrome-sdk (and not the raw ebuild), the test will 329 # need some additional runtime data located in the SDK cache. 330 if (cros_sdk_version != "") { 331 assert(defined(generated_script), 332 "Must specify where to place generated test launcher script via " + 333 "'generated_script'") 334 335 generate_chromeos_sdk_deps(target_name + "_cros_deps__helper") { 336 is_tast = is_tast 337 deploy_chrome = deploy_chrome 338 } 339 } 340 341 generate_wrapper(target_name) { 342 executable = "//build/chromeos/test_runner.py" 343 wrapper_script = generated_script 344 executable_args = [] 345 346 if (defined(runtime_deps_file)) { 347 write_runtime_deps = runtime_deps_file 348 } 349 350 # Build executable_args for the three different test types: GTest, Tast, 351 # and host-side commands (eg telemetry). 352 if (defined(test_exe)) { 353 executable_args += [ 354 "gtest", 355 "--test-exe", 356 test_exe, 357 ] 358 359 # This target is not a gtest unit test, but an integration test suite. 360 # Similar to interactive ui tests, it would start a full browser and 361 # then do testing. 362 # See more at //docs/testing/chromeos_integration. 363 if (test_exe == "chromeos_integration_tests") { 364 # Run the test sudo helper. 365 executable_args += [ "--run-test-sudo-helper" ] 366 367 if (is_chromeos_ash) { 368 # For ash, it need to first stop the existing ash. 369 executable_args += [ "--stop-ui" ] 370 } 371 372 # Lacros need to know the wayland socket file created by Ash. 373 # In this way, Lacros will be connected to the system Ash. 374 if (is_chromeos_lacros) { 375 executable_args += [ 376 "--env-var", 377 "XDG_RUNTIME_DIR", 378 "/run/chrome", 379 ] 380 } 381 382 # Make the tests match the browser's selinux tags so it gets the same 383 # security context as the browser would. 384 executable_args += [ "--set-selinux-label=chromeos_integration_tests=u:object_r:chrome_browser_exec:s0" ] 385 } 386 if (defined(runtime_deps_file)) { 387 executable_args += [ 388 "--runtime-deps-path", 389 rebase_path(runtime_deps_file, root_build_dir), 390 ] 391 } 392 } else if (is_tast) { 393 # When --tast-tests is specified, test_runner.py will call 394 # local_test_runner on the VM to run the set of tests. 395 executable_args += [ 396 "tast", 397 "--suite-name", 398 target_name, 399 ] 400 if (defined(tast_attr_expr)) { 401 executable_args += [ 402 "--attr-expr", 403 tast_attr_expr, 404 ] 405 } else { 406 foreach(test, tast_tests) { 407 executable_args += [ 408 "-t", 409 test, 410 ] 411 } 412 } 413 if (defined(tast_vars)) { 414 foreach(var, tast_vars) { 415 executable_args += [ 416 "--tast-var", 417 var, 418 ] 419 } 420 } 421 if (dcheck_always_on) { 422 executable_args += [ 423 "--tast-extra-use-flags", 424 "chrome_dcheck", 425 ] 426 } 427 } else { 428 executable_args += [ "host-cmd" ] 429 } 430 executable_args += [ 431 "--cros-cache", 432 "build/cros_cache/", 433 "--path-to-outdir", 434 rebase_path(root_out_dir, "//"), 435 "-v", 436 ] 437 438 if (!is_tast && strip_chrome) { 439 executable_args += [ "--strip-chrome" ] 440 } 441 442 if (!skip_generating_board_args) { 443 executable_args += [ 444 "--board", 445 cros_board, 446 ] 447 448 _cros_is_vm = false 449 foreach(b, string_split(cros_boards_with_qemu_images, ":")) { 450 if (cros_board == b) { 451 _cros_is_vm = true 452 } 453 } 454 if (_cros_is_vm) { 455 executable_args += [ "--use-vm" ] 456 } else { 457 executable_args += [ "--flash" ] 458 } 459 } 460 461 # If we have public Chromium builds, use public Chromium OS images when 462 # flashing the test device. 463 if (!is_chrome_branded) { 464 executable_args += [ "--public-image" ] 465 } 466 467 if (deploy_lacros) { 468 executable_args += [ "--deploy-lacros" ] 469 } 470 471 if (deploy_chrome && !defined(test_exe)) { 472 executable_args += [ "--deploy-chrome" ] 473 } 474 475 # executable_args should be finished, now build the data and deps lists. 476 deps = [ "//testing/buildbot/filters:chromeos_filters" ] 477 if (defined(invoker.deps)) { 478 deps += invoker.deps 479 } 480 data = [ 481 "//.vpython3", 482 483 # We use android test-runner's results libs to construct gtest output 484 # json. 485 "//build/android/pylib/__init__.py", 486 "//build/android/pylib/base/", 487 "//build/android/pylib/results/", 488 "//build/chromeos/", 489 "//build/util/", 490 "//third_party/chromite/", 491 ] 492 493 if (defined(invoker.data)) { 494 data += invoker.data 495 } 496 497 data_deps = [ "//testing:test_scripts_shared" ] 498 if (cros_sdk_version != "") { 499 data_deps += [ ":" + target_name + "_cros_deps__helper" ] 500 } 501 if (defined(invoker.data_deps)) { 502 data_deps += invoker.data_deps 503 } 504 } 505} 506 507template("tast_test") { 508 forward_variables_from(invoker, "*") 509 510 # Default the expression to match any chrome-related test. 511 if (!defined(tast_attr_expr) && !defined(tast_tests)) { 512 # The following expression filters out all non-critical tests. See the link 513 # below for more details: 514 # https://chromium.googlesource.com/chromiumos/platform/tast/+/main/docs/test_attributes.md 515 tast_attr_expr = "\"group:mainline\" && \"dep:chrome\"" 516 517 if (defined(enable_tast_informational_tests) && 518 enable_tast_informational_tests) { 519 tast_attr_expr += " && informational" 520 } else { 521 tast_attr_expr += " && !informational" 522 } 523 if (!is_chrome_branded) { 524 tast_attr_expr += " && !\"dep:chrome_internal\"" 525 } 526 } else { 527 assert(defined(tast_attr_expr) != defined(tast_tests), 528 "Specify one of tast_tests or tast_attr_expr.") 529 } 530 531 _data_deps = [ 532 "//:chromiumos_preflight", # Builds the browser. 533 "//chromeos:cros_chrome_deploy", # Adds additional browser run-time deps. 534 535 # Tools used to symbolize Chrome crash dumps. 536 # TODO(crbug.com/1156772): Remove these if/when all tests pick them up by 537 # default. 538 "//third_party/breakpad:dump_syms", 539 "//third_party/breakpad:minidump_dump", 540 "//third_party/breakpad:minidump_stackwalk", 541 ] 542 _data = [ "//components/crash/content/tools/generate_breakpad_symbols.py" ] 543 544 if (is_skylab) { 545 generate_skylab_tast_filter(target_name) { 546 # chromite.deploy_chrome is needed for sideloading Chrome. 547 data = _data + [ "//third_party/chromite/" ] 548 data_deps = _data_deps 549 550 # To disable a test on specific milestones, add it to the appropriate 551 # collection in the following file 552 tast_control = "//chromeos/tast_control.gni" 553 } 554 } else { 555 # Append any disabled tests to the expression. 556 if (defined(tast_disabled_tests)) { 557 assert(defined(tast_attr_expr), 558 "tast_attr_expr must be used when specifying tast_disabled_tests.") 559 foreach(_test_name, tast_disabled_tests) { 560 tast_attr_expr += " && !\"name:${_test_name}\"" 561 } 562 } 563 if (defined(tast_attr_expr)) { 564 tast_attr_expr = "( " + tast_attr_expr + " )" 565 } 566 generate_runner_script(target_name) { 567 testonly = true 568 generated_script = "$root_build_dir/bin/run_${target_name}" 569 runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps" 570 deploy_chrome = true 571 572 data_deps = _data_deps 573 if (!defined(deploy_lacros_chrome)) { 574 deploy_lacros_chrome = false 575 } 576 deploy_lacros = deploy_lacros_chrome 577 data = _data 578 if (deploy_lacros_chrome) { 579 data += [ 580 # A script needed to launch Lacros in Lacros Tast tests. 581 "//build/lacros/mojo_connection_lacros_launcher.py", 582 ] 583 584 # By default, tast tests download a lacros-chrome from a gcs location and 585 # use it for testing. To support running lacros tast tests from Chromium CI, 586 # a Var is added to support pointing the tast tests to use a specified 587 # pre-deployed lacros-chrome. The location is decided by: 588 # https://source.chromium.org/chromium/chromium/src/+/main:third_party/chromite/scripts/deploy_chrome.py;l=80;drc=86f1234a4be8e9574442e076cdc835897f7bea61 589 tast_vars = [ "lacros.DeployedBinary=/usr/local/lacros-chrome" ] 590 } 591 } 592 } 593} 594 595template("lacros_tast_tests") { 596 forward_variables_from(invoker, 597 [ 598 "tast_attr_expr", 599 "tast_disabled_tests", 600 "tast_tests", 601 "tast_control", 602 ]) 603 assert(defined(tast_attr_expr) != defined(tast_tests), 604 "Specify one of tast_tests or tast_attr_expr.") 605 606 _lacros_data_deps = [ 607 "//chrome", # Builds the browser. 608 609 # Tools used to symbolize Chrome crash dumps. 610 # TODO(crbug.com/1156772): Remove these if/when all tests pick them up by 611 # default. 612 "//third_party/breakpad:dump_syms", 613 "//third_party/breakpad:minidump_dump", 614 "//third_party/breakpad:minidump_stackwalk", 615 ] 616 617 _lacros_data = [ 618 "//components/crash/content/tools/generate_breakpad_symbols.py", 619 620 # A script needed to launch Lacros in Lacros Tast tests. 621 "//build/lacros/mojo_connection_lacros_launcher.py", 622 ] 623 624 if (is_skylab) { 625 generate_skylab_tast_filter(target_name) { 626 data = _lacros_data + [ 627 "//.vpython3", 628 "//third_party/chromite/", 629 ] 630 data_deps = _lacros_data_deps 631 632 # To disable a test on specific milestones, add it to the appropriate 633 # collection in the following file 634 tast_control = "//chromeos/tast_control.gni" 635 } 636 } else { 637 # Append any disabled tests to the expression. 638 if (defined(tast_disabled_tests)) { 639 assert(defined(tast_attr_expr), 640 "tast_attr_expr must be used when specifying tast_disabled_tests.") 641 foreach(_test, tast_disabled_tests) { 642 _excluded_test_name_and_board = [] 643 _excluded_test_name_and_board = string_split(_test, "@") + [ "" ] 644 _excluded_test_name = _excluded_test_name_and_board[0] 645 _excluded_board = _excluded_test_name_and_board[1] 646 if (_excluded_board == "" || _excluded_board == cros_board) { 647 tast_attr_expr += " && !\"name:${_excluded_test_name}\"" 648 } 649 } 650 } 651 if (defined(tast_attr_expr)) { 652 tast_attr_expr = "( " + tast_attr_expr + " )" 653 } 654 generate_runner_script(target_name) { 655 testonly = true 656 deploy_lacros = true 657 generated_script = "$root_build_dir/bin/run_${target_name}" 658 runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps" 659 660 # At build time, Lacros tests don't know whether they'll run on VM or HW, 661 # and instead, these flags are specified at runtime when invoking the 662 # generated runner script. 663 skip_generating_board_args = true 664 665 # By default, tast tests download a lacros-chrome from a gcs location and 666 # use it for testing. To support running lacros tast tests from Chromium CI, 667 # a Var is added to support pointing the tast tests to use a specified 668 # pre-deployed lacros-chrome. The location is decided by: 669 # https://source.chromium.org/chromium/chromium/src/+/main:third_party/chromite/scripts/deploy_chrome.py;l=80;drc=86f1234a4be8e9574442e076cdc835897f7bea61 670 tast_vars = [ "lacros.DeployedBinary=/usr/local/lacros-chrome" ] 671 672 data_deps = _lacros_data_deps 673 674 data = _lacros_data 675 } 676 } 677} 678