# Copyright 2018 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. import("//build/config/chrome_build.gni") import("//build/config/chromeos/args.gni") import("//build/config/chromeos/ui_mode.gni") import("//build/config/gclient_args.gni") import("//build/config/python.gni") import("//build/util/generate_wrapper.gni") assert((is_chromeos_ash || is_chromeos_lacros) && is_chromeos_device) # Determine the real paths for various items in the SDK, which may be used # in the 'generate_runner_script' template below. We do so outside the template # to confine exec_script to a single invocation. if (cros_sdk_version != "") { # Ideally these should be maps, however, gn doesn't support map, so using a # list of list to simulate a map: # [key1, [value1, value2, ...]], [key2, [value1, value2, ...]], where # the keys are boards and values are symlinks or symlink targets, and the # mapping shouldn't be used for anything else. # # A sample usage is: # foreach(m, _symlink_targets_map) { # if(m[0] == target_key) { # target_value = m[1] # } # } # _symlink_map = [] _symlink_targets_map = [] if (is_chromeos_ash) { _potential_test_boards = [ cros_board ] } else { _potential_test_boards = [] if (cros_boards != "") { _potential_test_boards += string_split(cros_boards, ":") } if (cros_boards_with_qemu_images != "") { _potential_test_boards += string_split(cros_boards_with_qemu_images, ":") } } foreach(b, _potential_test_boards) { _cache_path_prefix = "//build/cros_cache/chrome-sdk/symlinks/${b}+${cros_sdk_version}" _cros_is_vm = false foreach(b1, string_split(cros_boards_with_qemu_images, ":")) { if (b == b1) { _cros_is_vm = true } } _symlinks = [] _symlinks = [ # Tast harness & test data. rebase_path("${_cache_path_prefix}+chromeos-base/tast-cmd"), rebase_path("${_cache_path_prefix}+chromeos-base/tast-remote-tests-cros"), # Binutils (and other toolchain tools) used to deploy Chrome to the device. rebase_path( "${_cache_path_prefix}+environment_chromeos-base_chromeos-chrome.tar.xz"), rebase_path("${_cache_path_prefix}+target_toolchain"), ] if (_cros_is_vm) { # VM-related tools. _symlinks += [ rebase_path("${_cache_path_prefix}+sys-firmware/seabios"), rebase_path("${_cache_path_prefix}+chromiumos_test_image.tar.xz"), rebase_path("${_cache_path_prefix}+app-emulation/qemu"), ] } _symlink_map += [ [ b, _symlinks, ] ] } _all_symlinks = [] foreach(m, _symlink_map) { _all_symlinks += m[1] } _all_symlink_targets = exec_script("//build/get_symlink_targets.py", _all_symlinks, "list lines") _index = 0 foreach(m, _symlink_map) { _symlink_targets = [] foreach(_, m[1]) { _symlink_targets += [ _all_symlink_targets[_index] ] _index += 1 } _symlink_targets_map += [ [ m[0], _symlink_targets, ] ] } } # Creates a script at $generated_script that can be used to launch a cros VM # and optionally run a test within it. # Args: # test_exe: Name of test binary located in the out dir. This will get copied # to the VM and executed there. # tast_attr_expr: Tast expression to pass to local_test_runner on the VM. # tast_tests: List of Tast tests to run on the VM. Note that when this is # specified, the target name used to invoke this template will be # designated as the "name" of this test and will primarly used for test # results tracking and displaying (eg: flakiness dashboard). # generated_script: Path to place the generated script. # deploy_chrome: If true, deploys a locally built chrome located in the root # build dir to the VM or DUT after launching it. # deploy_lacros: If true, deploys a locally built Lacros located in the root # build dir to the VM or DUT after launching it. # runtime_deps_file: Path to file listing runtime deps for the test. If set, # all files listed will be copied to the VM before testing. # skip_generating_board_args: By default, this template generates an '--board' # arg with corresponding '--flash' or '--use-vm' args for device and vm # respectively. This argument instructs the template to skip generating # them, and it's designed for use cases where one builds for one board # (e.g. amd64-generic), but tests on a different board (e.g. eve). # tast_vars: A list of "key=value" runtime variable pairs to pass to invoke # the Tast tests. For more details, please see: # https://chromium.googlesource.com/chromiumos/platform/tast/+/HEAD/docs/writing_tests.md#Runtime-variables template("generate_runner_script") { forward_variables_from(invoker, [ "deploy_chrome", "deploy_lacros", "generated_script", "runtime_deps_file", "skip_generating_board_args", "tast_attr_expr", "tast_tests", "tast_vars", "testonly", "test_exe", ]) if (!defined(skip_generating_board_args)) { skip_generating_board_args = false } if (skip_generating_board_args) { # cros_board is not needed, so setting it to empty to avoid being used # accidentally below. cros_board = "" not_needed([ cros_board ]) } if (!defined(deploy_chrome)) { deploy_chrome = false } if (!defined(deploy_lacros)) { deploy_lacros = false } assert(!(deploy_chrome && deploy_lacros), "deploy_chrome and deploy_lacros are exclusive.") is_tast = defined(tast_attr_expr) || defined(tast_tests) assert(!(is_tast && defined(test_exe)), "Tast tests are invoked from binaries shipped with the VM image. " + "There should be no locally built binary needed.") assert(is_tast || !defined(tast_vars), "tast_vars is only support for Tast tests") # If we're in the cros chrome-sdk (and not the raw ebuild), the test will # need some additional runtime data located in the SDK cache. _sdk_data = [] if (cros_sdk_version != "") { assert(defined(generated_script), "Must specify where to place generated test launcher script via " + "'generated_script'") foreach(b, _potential_test_boards) { _cros_is_vm = false foreach(b1, string_split(cros_boards_with_qemu_images, ":")) { if (b == b1) { _cros_is_vm = true } } # Determine the real paths for various items in the SDK, which may be used # in the 'generate_runner_script' template below. if (is_tast || _cros_is_vm || deploy_chrome) { _symlink_targets = [] foreach(m, _symlink_targets_map) { if (b == m[0]) { _symlink_targets = [] _symlink_targets = m[1] } } if (is_tast) { # Add tast sdk items. _sdk_data += [ _symlink_targets[0], _symlink_targets[1], ] } if (deploy_chrome) { # To deploy chrome to the VM, it needs to be stripped down to fit into # the VM. This is done by using binutils in the toolchain. So add the # toolchain to the data. _sdk_data += [ _symlink_targets[2], _symlink_targets[3], ] } if (_cros_is_vm) { # Add vm sdk items. _sdk_data += [ _symlink_targets[4], _symlink_targets[5], _symlink_targets[6], ] } } } } generate_wrapper(target_name) { executable = "//build/chromeos/test_runner.py" use_vpython3 = true wrapper_script = generated_script executable_args = [] if (defined(runtime_deps_file)) { write_runtime_deps = runtime_deps_file } # Build executable_args for the three different test types: GTest, Tast, # and host-side commands (eg telemetry). if (defined(test_exe)) { executable_args += [ "gtest", "--test-exe", test_exe, ] if (defined(runtime_deps_file)) { executable_args += [ "--runtime-deps-path", rebase_path(runtime_deps_file, root_build_dir), ] } } else if (is_tast) { # When --tast-tests is specified, test_runner.py will call # local_test_runner on the VM to run the set of tests. executable_args += [ "tast", "--suite-name", target_name, ] if (defined(tast_attr_expr)) { executable_args += [ "--attr-expr", tast_attr_expr, ] } else { foreach(test, tast_tests) { executable_args += [ "-t", test, ] } } if (defined(tast_vars)) { foreach(var, tast_vars) { executable_args += [ "--tast-var", var, ] } } } else { executable_args += [ "host-cmd" ] } executable_args += [ "--cros-cache", "build/cros_cache/", "--path-to-outdir", rebase_path(root_out_dir, "//"), "-v", ] if (!skip_generating_board_args) { executable_args += [ "--board", cros_board, ] _cros_is_vm = false foreach(b, string_split(cros_boards_with_qemu_images, ":")) { if (cros_board == b) { _cros_is_vm = true } } if (_cros_is_vm) { executable_args += [ "--use-vm" ] } else { executable_args += [ "--flash" ] } } # If we have public Chromium builds, use public Chromium OS images when # flashing the test device. if (!is_chrome_branded) { executable_args += [ "--public-image" ] } if (deploy_lacros) { executable_args += [ "--deploy-lacros" ] } if (deploy_chrome && !defined(test_exe) && !is_tast) { executable_args += [ "--deploy-chrome" ] } # executable_args should be finished, now build the data and deps lists. deps = [ "//testing/buildbot/filters:chromeos_filters" ] if (defined(invoker.deps)) { deps += invoker.deps } data = [ "//.vpython", "//.vpython3", # We use android test-runner's results libs to construct gtest output # json. "//build/android/pylib/__init__.py", "//build/android/pylib/base/", "//build/android/pylib/results/", "//build/chromeos/", "//build/util/", # Needed for various SDK components used below. "//build/cros_cache/chrome-sdk/misc/", "//build/cros_cache/chrome-sdk/symlinks/", # The LKGM file controls what version of the VM image to download. Add it # as data here so that changes to it will trigger analyze. "//chromeos/CHROMEOS_LKGM", "//third_party/chromite/", ] data += _sdk_data if (defined(invoker.data)) { data += invoker.data } data_deps = [ "//testing:test_scripts_shared" ] if (defined(invoker.data_deps)) { data_deps += invoker.data_deps } } } template("tast_test") { forward_variables_from(invoker, "*") # Default the expression to match any chrome-related test. if (!defined(tast_attr_expr) && !defined(tast_tests)) { # The following expression filters out all non-critical tests. See the link # below for more details: # https://chromium.googlesource.com/chromiumos/platform/tast/+/main/docs/test_attributes.md tast_attr_expr = "\"group:mainline\" && \"dep:chrome\"" if (defined(enable_tast_informational_tests) && enable_tast_informational_tests) { tast_attr_expr += " && informational" } else { tast_attr_expr += " && !informational" } if (!is_chrome_branded) { tast_attr_expr += " && !\"dep:chrome_internal\"" } } else { assert(defined(tast_attr_expr) != defined(tast_tests), "Specify one of tast_tests or tast_attr_expr.") } # Append any disabled tests to the expression. if (defined(tast_disabled_tests)) { assert(defined(tast_attr_expr), "tast_attr_expr must be used when specifying tast_disabled_tests.") foreach(test, tast_disabled_tests) { tast_attr_expr += " && !\"name:${test}\"" } } if (defined(tast_attr_expr)) { tast_attr_expr = "( " + tast_attr_expr + " )" } generate_runner_script(target_name) { testonly = true generated_script = "$root_build_dir/bin/run_${target_name}" runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps" deploy_chrome = true data_deps = [ "//:chromiumos_preflight", # Builds the browser. "//chromeos:cros_chrome_deploy", # Adds additional browser run-time deps. # Tools used to symbolize Chrome crash dumps. # TODO(crbug.com/1156772): Remove these if/when all tests pick them up by # default. "//third_party/breakpad:dump_syms", "//third_party/breakpad:minidump_dump", "//third_party/breakpad:minidump_stackwalk", ] data = [ "//components/crash/content/tools/generate_breakpad_symbols.py" ] } } template("lacros_tast_tests") { forward_variables_from(invoker, [ "tast_attr_expr", "tast_disabled_tests", "tast_tests", ]) assert(defined(tast_attr_expr) != defined(tast_tests), "Specify one of tast_tests or tast_attr_expr.") # Append any disabled tests to the expression. if (defined(tast_disabled_tests)) { assert(defined(tast_attr_expr), "tast_attr_expr must be used when specifying tast_disabled_tests.") foreach(test, tast_disabled_tests) { tast_attr_expr += " && !\"name:${test}\"" } } if (defined(tast_attr_expr)) { tast_attr_expr = "( " + tast_attr_expr + " )" } generate_runner_script(target_name) { testonly = true deploy_lacros = true generated_script = "$root_build_dir/bin/run_${target_name}" runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps" # At build time, Lacros tests don't know whether they'll run on VM or HW, # and instead, these flags are specified at runtime when invoking the # generated runner script. skip_generating_board_args = true # By default, tast tests download a lacros-chrome from a gcs location and # use it for testing. To support running lacros tast tests from Chromium CI, # a Var is added to support pointing the tast tests to use a specified # pre-deployed lacros-chrome. The location is decided by: # https://source.chromium.org/chromium/chromium/src/+/main:third_party/chromite/scripts/deploy_chrome.py;l=80;drc=86f1234a4be8e9574442e076cdc835897f7bea61 tast_vars = [ "lacrosDeployedBinary=/usr/local/lacros-chrome" ] data_deps = [ "//chrome", # Builds the browser. # Tools used to symbolize Chrome crash dumps. # TODO(crbug.com/1156772): Remove these if/when all tests pick them up by # default. "//third_party/breakpad:dump_syms", "//third_party/breakpad:minidump_dump", "//third_party/breakpad:minidump_stackwalk", ] data = [ "//components/crash/content/tools/generate_breakpad_symbols.py", # A script needed to launch Lacros in Lacros Tast tests. "//build/lacros/mojo_connection_lacros_launcher.py", ] } } template("generate_skylab_runner_script") { forward_variables_from(invoker, [ "generated_script", "test_exe", ]) action(target_name) { script = "//build/chromeos/gen_skylab_runner.py" outputs = [ generated_script ] args = [ "--test-exe", test_exe, "--output", rebase_path(generated_script, root_build_dir), ] deps = [ "//testing/buildbot/filters:chromeos_filters" ] if (defined(invoker.deps)) { deps += invoker.deps } data = [ generated_script ] if (defined(invoker.data)) { data += invoker.data } data_deps = [ "//testing:test_scripts_shared" ] if (defined(invoker.data_deps)) { data_deps += invoker.data_deps } } }