1# Copyright 2021 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/rust.gni") 6import("//build/rust/rust_unit_tests_group.gni") 7 8# Defines a Rust unit test. 9# 10# This generates an executable + a script that can be run on Chromium bots. 11# Future iterations of this template may do something smarter with the test 12# code in order to automatically contribute it to test steps on the bots. 13# 14# Parameters 15# 16# sources 17# edition (optional) 18# allow_unsafe (optional) 19# configs (optional) 20# deps (optional) 21# crate_root (optional) 22# features (optional) 23# rustflags (optional) 24# inputs (optional) 25# All as in rust_static_library. 26# 27# Example of usage: 28# 29# rust_unit_test("foo_tests") { 30# deps = [ 31# "//third_party/rust/test_utils/v1:lib", 32# ] 33# sources = [ "src/lib.rs" ] 34# } 35# 36# Implementation note: you might assume it makes sense to implement this 37# in terms of rust_target in order to avoid the duplication of logic around 38# features and editions. We don't do that because rust_target actually 39# depends on this template in order to build embedded unit tests 40# (and therefore depending on rust_target here would lead to an infinite 41# import loop). 42 43template("rust_unit_test") { 44 assert(can_build_rust_unit_tests) 45 if (defined(invoker.crate_name)) { 46 _crate_name = invoker.crate_name 47 } else { 48 _crate_name = target_name 49 } 50 if (defined(invoker.crate_root)) { 51 _crate_root = invoker.crate_root 52 } else { 53 _crate_root = "src/lib.rs" 54 } 55 _rustflags = invoker.rustflags 56 if (defined(invoker.features)) { 57 foreach(i, invoker.features) { 58 _rustflags += [ "--cfg=feature=\"${i}\"" ] 59 } 60 } 61 _configs = invoker.configs 62 _edition = "2021" 63 if (defined(invoker.edition)) { 64 _edition = invoker.edition 65 } 66 _configs += [ "//build/rust:edition_${_edition}" ] 67 68 # We require that all source files are listed, even though this is 69 # not a requirement for rustc. The reason is to ensure that tools 70 # such as `gn deps` give the correct answer, and thus we trigger 71 # the right test suites etc. on code change. 72 # TODO(crbug.com/40200431) - verify this is correct 73 assert(defined(invoker.sources), "sources must be listed") 74 75 _exe_target_name = target_name + "_exe" 76 rust_unit_tests_group(target_name) { 77 deps = [ ":$_exe_target_name" ] 78 } 79 80 # The OUT_DIR for a crate's tests should point to the same OUT_DIR that the 81 # library it's testing used. The `env_out_dir` variable can be used to specify 82 # that directory. 83 if (defined(invoker.env_out_dir)) { 84 _env_out_dir = invoker.env_out_dir 85 } else { 86 _env_out_dir = target_gen_dir 87 } 88 89 executable(_exe_target_name) { 90 testonly = true 91 forward_variables_from(invoker, 92 "*", 93 [ 94 "allow_unsafe", 95 "edition", 96 "features", 97 "rustflags", 98 "configs", 99 "crate_name", 100 "crate_root", 101 "env_out_dir", 102 ]) 103 if (!defined(output_name) || output_name == "") { 104 output_name = _crate_name 105 } 106 107 rustflags = [ 108 "--cfg", 109 "feature=\"test\"", 110 "--test", 111 ] 112 rustflags += _rustflags 113 configs = [] 114 configs = _configs 115 crate_name = _crate_name 116 crate_root = _crate_root 117 if (!defined(rustenv)) { 118 rustenv = [] 119 } 120 121 rustenv += [ "OUT_DIR=" + 122 rebase_path(_env_out_dir, get_path_info(_crate_root, "dir")) ] 123 metadata = { 124 # Consumed by "rust_unit_tests_group" gni template. 125 rust_unit_test_executables = [ _crate_name ] 126 } 127 128 # Duplicated from rust_target since we didn't use the rust_executable 129 # template as it causes a GN cycle. 130 if (!defined(deps)) { 131 deps = [] 132 } 133 if (!defined(invoker.no_chromium_prelude) || !invoker.no_chromium_prelude) { 134 if (enable_chromium_prelude) { 135 deps += [ "//build/rust/chromium_prelude" ] 136 } 137 } 138 } 139} 140 141set_defaults("rust_unit_test") { 142 configs = default_executable_configs 143 deps = [] 144 rustflags = [] 145} 146