blob: b6cf3b2181d47ffbb902a1d19e8313f89478a723 [file] [log] [blame]
# Copyright 2021 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/rust.gni")
import("//build/rust/rust_unit_tests_group.gni")
# Defines a Rust unit test.
#
# This generates an executable + a script that can be run on Chromium bots.
# Future iterations of this template may do something smarter with the test
# code in order to automatically contribute it to test steps on the bots.
#
# Parameters
#
# sources
# edition (optional)
# allow_unsafe (optional)
# configs (optional)
# deps (optional)
# crate_root (optional)
# features (optional)
# rustflags (optional)
# inputs (optional)
# All as in rust_static_library.
#
# Example of usage:
#
# rust_unit_test("foo_tests") {
# deps = [
# "//third_party/rust/test_utils/v1:lib",
# ]
# sources = [ "src/lib.rs" ]
# }
#
# Implementation note: you might assume it makes sense to implement this
# in terms of rust_target in order to avoid the duplication of logic around
# features and editions. We don't do that because rust_target actually
# depends on this template in order to build embedded unit tests
# (and therefore depending on rust_target here would lead to an infinite
# import loop).
template("rust_unit_test") {
assert(can_build_rust_unit_tests)
if (defined(invoker.crate_name)) {
_crate_name = invoker.crate_name
} else {
_crate_name = target_name
}
if (defined(invoker.crate_root)) {
_crate_root = invoker.crate_root
} else {
_crate_root = "src/lib.rs"
}
_rustflags = invoker.rustflags
if (defined(invoker.features)) {
foreach(i, invoker.features) {
_rustflags += [ "--cfg=feature=\"${i}\"" ]
}
}
_configs = invoker.configs
_edition = "2021"
if (defined(invoker.edition)) {
_edition = invoker.edition
}
_configs += [ "//build/rust:edition_${_edition}" ]
# We require that all source files are listed, even though this is
# not a requirement for rustc. The reason is to ensure that tools
# such as `gn deps` give the correct answer, and thus we trigger
# the right test suites etc. on code change.
# TODO(crbug.com/40200431) - verify this is correct
assert(defined(invoker.sources), "sources must be listed")
_exe_target_name = target_name + "_exe"
rust_unit_tests_group(target_name) {
deps = [ ":$_exe_target_name" ]
}
# The OUT_DIR for a crate's tests should point to the same OUT_DIR that the
# library it's testing used. The `env_out_dir` variable can be used to specify
# that directory.
if (defined(invoker.env_out_dir)) {
_env_out_dir = invoker.env_out_dir
} else {
_env_out_dir = target_gen_dir
}
# TODO(crbug.com/40778298): Arrange to run test executables on try bots.
# TODO(crbug.com/gn/146): Allow Rust executables to depend on C/C++ source
# sets.
# This is important in cases where Rust tests may depend upon C/C++
# dependencies.
executable(_exe_target_name) {
testonly = true
forward_variables_from(invoker,
"*",
[
"allow_unsafe",
"edition",
"features",
"rustflags",
"configs",
"crate_name",
"crate_root",
"env_out_dir",
])
if (!defined(output_name) || output_name == "") {
output_name = _crate_name
}
rustflags = [
"--cfg",
"feature=\"test\"",
"--test",
]
rustflags += _rustflags
configs = []
configs = _configs
crate_name = _crate_name
crate_root = _crate_root
if (!defined(rustenv)) {
rustenv = []
}
rustenv += [ "OUT_DIR=" +
rebase_path(_env_out_dir, get_path_info(_crate_root, "dir")) ]
metadata = {
# Consumed by "rust_unit_tests_group" gni template.
rust_unit_test_executables = [ _crate_name ]
}
# Duplicated from rust_target since we didn't use the rust_executable
# template as it causes a GN cycle.
if (!defined(deps)) {
deps = []
}
if (!defined(invoker.no_chromium_prelude) || !invoker.no_chromium_prelude) {
if (enable_chromium_prelude) {
deps += [ "//build/rust/chromium_prelude" ]
}
}
}
}
set_defaults("rust_unit_test") {
configs = default_executable_configs
deps = []
rustflags = []
}