| # Copyright 2018 The Fuchsia 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("//build/testing/host_test.gni") | 
 |  | 
 | # Defines a Rust unit test, without also compiling a separate binary or library | 
 | # target. | 
 | # | 
 | # Parameters | 
 | # | 
 | #   output_name (optional) | 
 | #   name (optional, deprecated) | 
 | #     Name of the test binary, also used as the crate name as defined in its | 
 | #     manifest file. If not specified, it is assumed to be the same as the | 
 | #     target name. | 
 | # | 
 | #   version | 
 | #     Semver version of the crate as seen on crates.io. | 
 | # | 
 | #   edition (optional) | 
 | #     Edition of the Rust language to be used. | 
 | #     Options are "2015" and "2018". Defaults to "2018". | 
 | # | 
 | #   configs (optional) | 
 | #     A list of config labels applying to this target. | 
 | # | 
 | #   enforce_source_listing (optional) | 
 | #     When true, enforces that any source files used by the Rust compiler are | 
 | #     listed in `sources`. Defaults to true. | 
 | # | 
 | #   sources (optional) | 
 | #     List of source files which this crate is allowed to compile. Only | 
 | #     allowed when `enforce_source_listing = true`. | 
 | #     The Rust compiler discovers source files by following `mod` declarations | 
 | #     starting at the `source_root`. The discovered source files must match this | 
 | #     list. | 
 | # | 
 | #   inputs (optional) | 
 | #     List of additional non-source files read by the compiler. These are typically | 
 | #     configuration or test-data files included in the build with the `include_str!` | 
 | #     macro. Only allowed when `enforce_source_listing = true`. | 
 | # | 
 | #   deps (optional) | 
 | #     List of rust_library GN targets on which this crate depends. | 
 | #     Third party crates can be included through paths like | 
 | #     "//third_party/rust_crates:<cratename>", | 
 | # | 
 | #   non_rust_deps (optional) | 
 | #     List of non-rust_library GN targets on which this crate depends. | 
 | # | 
 | #   test_environments (optional) | 
 | #     What environments the unit test should target. Only used here | 
 | #     for linux and mac tests, with a default value of a general linux/mac | 
 | #     environment (as a function of $current_os). | 
 | #     See environments parameter on //build/testing/test_spec.gni for more | 
 | #     details. | 
 |  | 
 | #   args (optional) | 
 | #     List of flags to pass directly to the test binary, e.g. | 
 | #     ["--nocapture"]. | 
 | # | 
 | #   source_root (optional) | 
 | #     Location of the crate root (e.g. `src/main.rs` or `src/lib.rs`). | 
 | #     This should usually be 'src/lib.rs/ for libraries (the default) | 
 | #     and `src/main.rs` for binaries. | 
 | # | 
 | #   features (optional) | 
 | #     A list of conditional compilation flags to enable. This can be used to set features for crates | 
 | #     built in-tree which are also published to crates.io. This would be passed to rustc as | 
 | #     '--cfg feature=XXX' | 
 | # | 
 | #   output_dir (optional) | 
 | #     Directory that the resulting test should be placed in. | 
 | #     See: `gn help output_dir` | 
 | # | 
 | # Example of usage: | 
 | # | 
 | #   rustc_test("foo_test") { | 
 | #     source_root = "src/foo_test.rs", | 
 | #     deps = [ | 
 | #       "//garnet/public/rust/bar", | 
 | #       "//third_party/rust_crates:clap", | 
 | #       "//third_party/rust_crates:serde", | 
 | #       "//third_party/rust_crates:slab", | 
 | #     ] | 
 | #     sources = [ "src/lib.rs" ] | 
 | #   } | 
 | template("rustc_test") { | 
 |   not_needed(invoker, | 
 |              [ | 
 |                "version", | 
 |                "edition", | 
 |                "force_opt", | 
 |                "testonly", | 
 |              ]) | 
 |  | 
 |   # default location for rust libraries | 
 |   source_root = "src/lib.rs" | 
 |   if (defined(invoker.source_root)) { | 
 |     source_root = invoker.source_root | 
 |   } | 
 |  | 
 |   # use the target name unless another name is specified | 
 |   assert(!(defined(invoker.output_name) && defined(invoker.name)), | 
 |          "Only one of output_name and name may be specified.") | 
 |   package_name = target_name | 
 |   if (defined(invoker.output_name)) { | 
 |     package_name = invoker.output_name | 
 |   } else if (defined(invoker.name)) { | 
 |     package_name = invoker.name | 
 |   } | 
 |  | 
 |   # built-in gn rules do not support dashes | 
 |   crate_name = string_replace(package_name, "-", "_") | 
 |  | 
 |   exe_target_name = target_name | 
 |  | 
 |   if (is_host) { | 
 |     exe_target_name = "${target_name}_executable" | 
 |     all_deps = [ ":${exe_target_name}" ] | 
 |     if (defined(invoker.deps)) { | 
 |       all_deps += invoker.deps | 
 |     } | 
 |     if (defined(invoker.non_rust_deps)) { | 
 |       all_deps += invoker.non_rust_deps | 
 |     } | 
 |  | 
 |     host_test(target_name) { | 
 |       binary_path = "${root_out_dir}/${crate_name}" | 
 |       deps = all_deps | 
 |       if (defined(invoker.test_environments)) { | 
 |         environments = invoker.test_environments | 
 |       } | 
 |       forward_variables_from(invoker, | 
 |                              [ | 
 |                                "args", | 
 |                                "visibility", | 
 |                              ]) | 
 |     } | 
 |   } else { | 
 |     # if not a host-side target, we don't need this since it doesn't | 
 |     # propogate to package.gni | 
 |     not_needed(invoker, [ "test_environments" ]) | 
 |   } | 
 |  | 
 |   # enable these features for the target | 
 |   features = [] | 
 |   if (defined(invoker.features)) { | 
 |     foreach(i, invoker.features) { | 
 |       features += [ "--cfg=feature=\"${i}\"" ] | 
 |     } | 
 |   } | 
 |  | 
 |   _sources = [] | 
 |   _deps = [] | 
 |  | 
 |   if (!defined(invoker.enforce_source_listing) || | 
 |       invoker.enforce_source_listing == true) { | 
 |     # fail early when the user forgets to list sources | 
 |     assert(defined(invoker.sources), "sources must be listed") | 
 |     _sources = invoker.sources | 
 |   } else { | 
 |     not_needed(invoker, [ "sources" ]) | 
 |  | 
 |     # This is a hack to workaround the fact that a GN `tool` invocation can't receive arbitrary input. | 
 |     # Add a sentinel value so that enforcement is skipped. | 
 |     _sources = [ "//build/rust/__SKIP_ENFORCEMENT__.rs" ] | 
 |  | 
 |     # Opting out of strict sources check requires that the package is present | 
 |     # in a global allow-list. | 
 |     _deps += [ "//build/rust:disable_strict_sources_check_allowlist" ] | 
 |   } | 
 |  | 
 |   executable(exe_target_name) { | 
 |     # anything defined with rustc_test MUST be a test target | 
 |     testonly = true | 
 |  | 
 |     configs = [] | 
 |     configs = invoker.configs | 
 |  | 
 |     crate_root = source_root | 
 |     output_name = crate_name | 
 |     crate_name = crate_name | 
 |  | 
 |     # tell rustc to compile in the test harness | 
 |     rustflags = features + [ "--test" ] | 
 |  | 
 |     deps = _deps | 
 |     if (defined(invoker.deps)) { | 
 |       deps += invoker.deps | 
 |     } | 
 |     if (defined(invoker.non_rust_deps)) { | 
 |       deps += invoker.non_rust_deps | 
 |     } | 
 |  | 
 |     # test_deps specified in the parent template (if not used directly) | 
 |     # should also be treated as normal dependencies | 
 |     if (defined(invoker.test_deps)) { | 
 |       deps += invoker.test_deps | 
 |     } | 
 |  | 
 |     data_deps = [] | 
 |     if (defined(invoker.data_deps)) { | 
 |       data_deps = invoker.data_deps | 
 |     } | 
 |     if (is_fuchsia) { | 
 |       # Dynamic linking applies to not only to libstd but to libtest as well, | 
 |       # which means we must depend on it as a data_dep to get it in our | 
 |       # package. | 
 |       _dynamic_rust_config = | 
 |           [ "//build/config/fuchsia:dynamic_rust_standard_library" ] | 
 |       if (configs + _dynamic_rust_config - _dynamic_rust_config != configs) { | 
 |         data_deps += [ "//build/toolchain/runtime:shared-rust-libtest-deps" ] | 
 |       } else { | 
 |         data_deps += [ "//build/toolchain/runtime:static-rust-libtest-deps" ] | 
 |       } | 
 |  | 
 |       deps += [ "//build/test:rust_test_metadata" ] | 
 |       metadata = { | 
 |         cmx_patches_walk = [ "//build/test:rust_test_metadata" ] | 
 |  | 
 |         # Used by the fuchsia_test_component_manifest() template. | 
 |         test_component_manifest_cml = [ | 
 |           { | 
 |             include = [ "src/sys/test_runners/rust/default.shard.cml" ] | 
 |           }, | 
 |         ] | 
 |       } | 
 |     } | 
 |  | 
 |     sources = _sources | 
 |  | 
 |     # in-tree default edition is 2018 | 
 |     if (defined(invoker.edition) && invoker.edition == "2015") { | 
 |       configs -= [ "//build/config:rust_edition_2018" ] | 
 |       configs += [ "//build/config:rust_edition_2015" ] | 
 |     } | 
 |  | 
 |     forward_variables_from(invoker, | 
 |                            [ | 
 |                              "inputs", | 
 |                              "output_dir", | 
 |                              "visibility", | 
 |                            ]) | 
 |   } | 
 | } |