xref: /aosp_15_r20/external/cronet/build/rust/rust_unit_test.gni (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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/1256930) - 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  # TODO(crbug.com/1229320): Arrange to run test executables on try bots.
90  # TODO(crbug.com/gn/146): Allow Rust executables to depend on C/C++ source
91  # sets.
92  # This is important in cases where Rust tests may depend upon C/C++
93  # dependencies.
94  executable(_exe_target_name) {
95    testonly = true
96    forward_variables_from(invoker,
97                           "*",
98                           [
99                             "allow_unsafe",
100                             "edition",
101                             "features",
102                             "rustflags",
103                             "configs",
104                             "crate_name",
105                             "crate_root",
106                             "env_out_dir",
107                           ])
108    if (!defined(output_name) || output_name == "") {
109      output_name = _crate_name
110    }
111
112    rustflags = [
113      "--cfg",
114      "feature=\"test\"",
115      "--test",
116    ]
117    rustflags += _rustflags
118    configs = []
119    configs = _configs
120    crate_name = _crate_name
121    crate_root = _crate_root
122    if (!defined(rustenv)) {
123      rustenv = []
124    }
125
126    rustenv += [ "OUT_DIR=" +
127                 rebase_path(_env_out_dir, get_path_info(_crate_root, "dir")) ]
128    metadata = {
129      # Consumed by "rust_unit_tests_group" gni template.
130      rust_unit_test_executables = [ _crate_name ]
131    }
132
133    # Duplicated from rust_target since we didn't use the rust_executable
134    # template as it causes a GN cycle.
135    if (!defined(deps)) {
136      deps = []
137    }
138    if (!defined(invoker.no_chromium_prelude) || !invoker.no_chromium_prelude) {
139      if (enable_chromium_prelude) {
140        deps += [ "//build/rust/chromium_prelude" ]
141      }
142    }
143  }
144}
145
146set_defaults("rust_unit_test") {
147  configs = default_executable_configs
148  deps = []
149  rustflags = []
150}
151