blob: 10af886af5ef7521080a7fe76cf251bef038b2c5 [file] [log] [blame]
# Copyright 2018 The Chromium Authors
# 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/dcheck_always_on.gni")
import("//build/config/gclient_args.gni")
import("//build/config/python.gni")
import("//build/util/generate_wrapper.gni")
assert(is_chromeos && 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}+autotest_server_package.tar.bz2"),
# 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 dependencies required by skylab testing. If passed the
# generated_script and test_exe this will generate the skylab runner script.
# If passed tast_attr_expr, tast_tests or tast_disabled_tests this will
# generate a filter file containing the expression for running tests in skylab.
# Args:
# generated_script: Name of the generated runner script created for test_exe
# test_exe: Name of the executable to run with the generated script.
# tast_attr_expr: Tast expression to determine tests to run. This creates the
# initial set of tests that can be further filtered..
# tast_tests: Names of tests to enable in tast. All other tests will be
# disabled that are not listed.
# tast_disabled_tests: Names of tests to disable in tast. All other tests that
# match the tast expression will still run.
# tast_control: gni file with collections of tests to be used for specific
# filters (e.g. "//chromeos/tast_control.gni"). Any lists of strings in
# this file will be used to generate additional tast expressions with
# those strings expanded into tests to disable (i.e. as && !"name:test").
# The name of those lists are then intended to be used to specify in
# test_suites.pyl which collection to be used on specific test suites.
template("generate_skylab_deps") {
forward_variables_from(invoker,
[
"generated_script",
"test_exe",
"tast_attr_expr",
"tast_tests",
"tast_disabled_tests",
"tast_control",
])
if (defined(test_exe) || defined(generated_script)) {
assert(defined(test_exe) && defined(generated_script),
"The test_exe and generated_script must both be defined when " +
"generating the skylab runner script")
action(target_name) {
script = "//build/chromeos/generate_skylab_deps.py"
outputs = [ generated_script ]
args = [
"generate-runner",
"--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
}
}
}
if (defined(tast_attr_expr) || defined(tast_tests) ||
defined(tast_disabled_tests)) {
if (defined(tast_disabled_tests)) {
assert(defined(tast_attr_expr),
"tast_attr_expr must be used when specifying tast_disabled_tests.")
}
_generated_filter = "$root_build_dir/bin/${target_name}.filter"
_skylab_args = [
"generate-filter",
"--output",
rebase_path(_generated_filter),
]
if (defined(tast_control)) {
_skylab_args += [
"--tast-control",
rebase_path(tast_control),
]
}
if (defined(tast_attr_expr)) {
_skylab_args += [
"--tast-expr",
tast_attr_expr,
]
}
if (defined(tast_tests)) {
foreach(_test, tast_tests) {
_skylab_args += [
"--enabled-tests",
_test,
]
}
}
if (defined(tast_disabled_tests)) {
foreach(_test, tast_disabled_tests) {
_excluded_test_name_and_board = []
_excluded_test_name_and_board = string_split(_test, "@") + [ "" ]
_excluded_test_name = _excluded_test_name_and_board[0]
_excluded_board = _excluded_test_name_and_board[1]
if (_excluded_board == "" || _excluded_board == cros_board) {
_skylab_args += [
"--disabled-tests",
_excluded_test_name,
]
}
}
}
action(target_name) {
script = "//build/chromeos/generate_skylab_deps.py"
if (defined(tast_control)) {
sources = [ tast_control ]
}
outputs = [ _generated_filter ]
args = _skylab_args
if (defined(invoker.data_deps)) {
data_deps = invoker.data_deps
}
data = [ _generated_filter ]
if (defined(invoker.data)) {
data += invoker.data
}
if (defined(invoker.deps)) {
deps = invoker.deps
}
}
}
}
# 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
# strip_chrome: If true, strips Chrome before deploying it for non-Tast tests.
# 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",
"strip_chrome",
"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
}
if (!defined(strip_chrome)) {
strip_chrome = false
}
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 (is_tast) {
not_needed([ "strip_chrome" ])
}
# 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] ]
}
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[1],
_symlink_targets[2],
]
}
if (_cros_is_vm) {
# Add vm sdk items.
_sdk_data += [
_symlink_targets[3],
_symlink_targets[4],
_symlink_targets[5],
]
}
}
}
}
generate_wrapper(target_name) {
executable = "//build/chromeos/test_runner.py"
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,
]
}
}
if (dcheck_always_on) {
executable_args += [
"--tast-extra-use-flags",
"chrome_dcheck",
]
}
} else {
executable_args += [ "host-cmd" ]
}
executable_args += [
"--cros-cache",
"build/cros_cache/",
"--path-to-outdir",
rebase_path(root_out_dir, "//"),
"-v",
]
if (!is_tast && strip_chrome) {
executable_args += [ "--strip-chrome" ]
}
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)) {
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 = [
"//.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/",
"//chrome/VERSION",
# 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, "*")
if (!defined(deploy_lacros_chrome)) {
deploy_lacros_chrome = false
}
# 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) {
_excluded_test_name_and_board = []
_excluded_test_name_and_board = string_split(_test, "@") + [ "" ]
_excluded_test_name = _excluded_test_name_and_board[0]
_excluded_board = _excluded_test_name_and_board[1]
if (_excluded_board == "" || _excluded_board == cros_board) {
tast_attr_expr += " && !\"name:${_excluded_test_name}\""
}
}
}
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
deploy_lacros = deploy_lacros_chrome
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" ]
if (deploy_lacros_chrome) {
data += [
# A script needed to launch Lacros in Lacros Tast tests.
"//build/lacros/mojo_connection_lacros_launcher.py",
]
}
}
}
template("lacros_tast_tests") {
forward_variables_from(invoker,
[
"tast_attr_expr",
"tast_disabled_tests",
"tast_tests",
"tast_control",
])
assert(defined(tast_attr_expr) != defined(tast_tests),
"Specify one of tast_tests or tast_attr_expr.")
_lacros_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",
]
_lacros_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",
]
if (is_skylab) {
generate_skylab_deps(target_name) {
data = _lacros_data
data_deps = _lacros_data_deps
# To disable a test on specific milestones, add it to the appropriate
# collection in the following file
tast_control = "//chromeos/tast_control.gni"
}
} else {
# 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) {
_excluded_test_name_and_board = []
_excluded_test_name_and_board = string_split(_test, "@") + [ "" ]
_excluded_test_name = _excluded_test_name_and_board[0]
_excluded_board = _excluded_test_name_and_board[1]
if (_excluded_board == "" || _excluded_board == cros_board) {
tast_attr_expr += " && !\"name:${_excluded_test_name}\""
}
}
}
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 = [ "lacros.DeployedBinary=/usr/local/lacros-chrome" ]
data_deps = _lacros_data_deps
data = _lacros_data
}
}
}