1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145

build / rust / rust_unit_test.gni [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
  }

  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 = []
}