Source code
Revision control
Copy as Markdown
Other Tools
# 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("//chromium/build/config/chrome_build.gni")
import("//chromium/build/config/chromeos/args.gni")
import("//chromium/build/config/chromeos/ui_mode.gni")
import("//chromium/build/config/gclient_args.gni")
import("//chromium/build/config/python.gni")
import("//chromium/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 =
"//chromium/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("//chromium/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:
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 = "//chromium/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.
"//chromium/build/android/pylib/__init__.py",
"//chromium/build/android/pylib/base/",
"//chromium/build/android/pylib/results/",
"//chromium/build/chromeos/",
"//chromium/build/util/",
# Needed for various SDK components used below.
"//chromium/build/cros_cache/chrome-sdk/misc/",
"//chromium/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:
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:
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.
"//chromium/build/lacros/mojo_connection_lacros_launcher.py",
]
}
}
template("generate_skylab_runner_script") {
forward_variables_from(invoker,
[
"generated_script",
"test_exe",
])
action(target_name) {
script = "//chromium/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
}
}
}