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