# `rust_test`

Rust test target.

## Description

Compiles a Rust test crate with `rustc --test`, then runs the produced test
binary through Once's generic test capability. The target can model unit tests
from a library root, or integration tests by setting `crate_root` to a test
crate entry file and depending on the library under test.

The runner uses the Rust test harness list output to populate
`once.test_results.v1`, stores the native test output, and returns the test
binary exit status to Once.

## Test results

Each case reports its status. A failed case carries the output the test
harness captured for it, truncated to 4000 characters, as its failure message.

The stable Rust test harness does not print per-test durations. When
`report_time` is `true`, the runner asks the harness for its timing report
with `-Z unstable-options --report-time` and sets `RUSTC_BOOTSTRAP=1` for the
test process, unless the test environment already sets that variable. The
runner first lists the tests with those flags, and only uses them for the run
when the binary accepts them and lists the same tests; otherwise the run uses
the plain invocation and cases report no duration. Ignored cases never report
a duration.

The test process, and any compiler or Cargo invocation it spawns, inherits
`RUSTC_BOOTSTRAP=1`, which lets those tools accept unstable features. Set
`report_time = false` for tests whose behavior depends on that variable, such
as tests that build crates whose build scripts probe for nightly features.

## Attributes

| Attribute | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `crate_name` | string | no | target name | Rust crate name passed to `rustc`; `-` and `.` are rewritten as `_` when omitted |
| `crate_root` | string | no | `src/lib.rs` | Package-relative test crate root |
| `edition` | string | no | `2021` | Rust edition passed to `rustc` |
| `features` | list&lt;string&gt; | no | `[]` | Cargo feature names lowered to `--cfg=feature=...` flags |
| `crate_features` | list&lt;string&gt; | no | `[]` | Bazel-compatible alias for `features` |
| `target` | string | no | host target | Rust target triple passed to `rustc --target` |
| `env` | map&lt;string, string&gt; | no | `{}` | Environment variables for `rustc` |
| `rustc_env` | map&lt;string, string&gt; | no | `{}` | Rust compiler environment variables |
| `rustc_env_files` | list&lt;string&gt; | no | `[]` | Files with `NAME=value` entries merged into the rustc environment before `env` and `rustc_env` |
| `rustc_flags` | list&lt;string&gt; | no | `[]` | Additional `rustc` flags appended after Once-managed flags |
| `cap_lints` | string | no | empty | Optional rustc lint cap passed as `--cap-lints` |
| `linker` | string | no | inferred | Optional linker path passed as `-C linker=...` |
| `linker_flags` | list&lt;string&gt; | no | `[]` | Additional linker flags lowered to `-C link-arg=...` |
| `native_linkopts` | list&lt;string&gt; | no | `[]` | Linker flags propagated to downstream native consumers when this target is used as native input |
| `exported_linker_flags` | list&lt;string&gt; | no | `[]` | Buck-compatible alias for native linker flags propagated to downstream native consumers |
| `exported_post_linker_flags` | list&lt;string&gt; | no | `[]` | Buck-compatible propagated linker flags appended after normal exported linker flags |
| `linker_script` | string | no | empty | Package-relative linker script passed to the linker and included in the compile action inputs |
| `data` | list&lt;string&gt; | no | `[]` | Runtime data file globs available to the test runner and propagated from Rust dependencies |
| `compile_data` | list&lt;string&gt; | no | `[]` | Bazel-compatible compile-time data file globs included in the rustc action inputs |
| `crate_aliases` | map&lt;string, string&gt; | no | `{}` | Map dependency label, package name, or crate name to the local extern crate name |
| `aliases` | map&lt;string, string&gt; | no | `{}` | Bazel-compatible alias map from dependency label or crate name to local extern crate name |
| `named_deps` | map&lt;string, string&gt; | no | `{}` | Buck-compatible alias map from local extern crate name to dependency label or crate name |
| `cargo_package` | string | no | empty | Cargo package name used to select direct external deps, including dev-dependencies, from a `cargo_dependencies` dependency set |
| `build_script` | string | no | empty | Package-relative Cargo build script path run before `rustc` |
| `build_script_tools` | list&lt;string&gt; | no | `[]` | Host tool names the build script invokes; each is resolved on the search path during graph loading |
| `cargo_config_env` | map&lt;string, string&gt; | no | `{}` | Environment declared by Cargo configuration, applied below `env`, `rustc_env`, and `test_env` |
| `args` | list&lt;string&gt; | no | `[]` | Arguments passed to the compiled test binary |
| `test_env` | map&lt;string, string&gt; | no | `{}` | Environment variables passed to the test runner |
| `test_cwd` | string | no | workspace root | Package-relative working directory for the test process |
| `env_inherit` | list&lt;string&gt; | no | `[]` | Host environment variable names inherited by the test runner before `test_env` overrides |
| `crate` | target | no | empty | Reserved Bazel-compatible reference to an already-built crate under test |
| `use_libtest_harness` | bool | no | `true` | Whether to use the Rust libtest harness. Only `true` is supported |
| `report_time` | bool | no | `true` | Whether to record per-test durations through the test harness timing report. See [Test results](#test-results) |
| `labels` | list&lt;string&gt; | no | `[]` | Labels exposed through `once_test_info` for test discovery |
| `timeout_ms` | int | no |  | Optional test timeout in milliseconds |
| `cacheable` | bool | no | `true` | Whether successful test results may be restored from the action cache. Disable it for tests whose outcome depends on host tools or configuration that are not declared inputs, such as tests that inherit `PATH` or `HOME` through `env_inherit`. Compilation stays cacheable |

Accepted but unsupported attributes: `default_deps`, `doc_deps`, `doc_env`, `doc_link_style`,
`doc_linker_flags`, `doc_named_deps`, `link_deps`, `link_style`,
`mapped_srcs`, `proc_macro_deps`, `rpath`, `runtime_dependency_handling`,
and `rustdoc_flags`. Non-empty values under `[target.attrs]` fail validation.
Use the dependency roles with the same names under `[target.dependencies]`.

## Dependency Edges

| Edge | Accepts | Description |
| --- | --- | --- |
| `deps` | `rust_crate`, `rust_proc_macro`, `rust_dependency_set`, `c_provider` | Rust crate dependencies consumed through `--extern`; C provider libraries and linker options are linked into the test executable |
| `proc_macro_deps` | `rust_proc_macro` | Procedural macros compiled for the execution host and passed to `rustc` through `--extern` |
| `link_deps` | `c_provider` | Native libraries and linker options consumed by the test executable |
| `bin_deps` | `rust_binary` | Executables the test spawns, exposed to the compiler and the test process as `CARGO_BIN_EXE_<binary name>` |

## Providers

The target emits `rust_test` and `once_test_info`.

## Capabilities

| Capability | Output groups |
| --- | --- |
| `build` | `binary` |
| `test` | `default`, `test_results`, `logs` |

## Outputs

| Output | Location |
| --- | --- |
| Test binary | `.once/out/<target>/<crate_name>` or `.exe` on Windows |
| Test results | `.once/out/<target>/test/test_results.json` |
| Test log | `.once/out/<target>/test/rust-libtest.log` |
| Native runner output | `.once/out/<target>/test/native_results.txt` |

## Environment

The test process starts with a cleared environment. Once gives it a private
`HOME` under the target's output directory, the standard system tool
directories on `PATH`, the package's `CARGO_*` description, a
`CARGO_BIN_EXE_<name>` entry for every `bin_deps` executable, and any
`cargo_config_env` entries. `env_inherit` names host variables to add, and
`test_env` overrides everything else.

## Limitations

A test that reads `CARGO_BIN_EXE_<name>` through the `env!` macro captures the
path at compile time, so the value belongs to the compiling action's execution
root. That is the same root the test runs in for an ordinary local build, but
not under a sandbox policy or remote execution, where each action gets its own
root. A test that reads the variable at run time instead works in every mode.

Test and run processes start with a fixed search path holding the standard
system tool directories. A test that invokes a program found there depends on
that program, and the action key records the search path rather than the
contents of what it finds, so a system tool upgraded in place does not
invalidate a cached test result. Pin such a tool through a target that
declares it instead of relying on the search path.

The `test` capability runs only host-target test binaries. A cross-target
`rust_test` can still be built, but running it needs a platform runner that is
not part of this target kind yet.

## Example

```toml
[[target]]
name = "hello"
kind = "rust_library"
srcs = ["src/**/*.rs"]

[target.attrs]
crate_name = "hello"
edition = "2021"

[[target]]
name = "hello_tests"
kind = "rust_test"
srcs = ["tests/**/*.rs"]
deps = ["./hello"]

[target.attrs]
crate_name = "hello_tests"
crate_root = "tests/greeting_test.rs"
edition = "2021"
labels = ["unit"]
```
