Skip to main content

bake_test_rust/
lib.rs

1// Released under the MIT License.
2// Copyright, 2026, by Samuel Williams.
3
4//! Shared test tasks for Rust projects using Bake.
5//!
6//! The crate provides `test` and `test:external`. Both tasks call the optional
7//! project task `test:before` before running Cargo tests.
8mod cargo;
9mod external;
10mod manifest;
11mod metadata;
12
13use bake::{Context, Error, Result};
14
15fn run_before_test_hook(context: &mut Context) -> Result<()> {
16    context.call_if_registered("test:before", &[])?;
17    Ok(())
18}
19
20/// Run the current Cargo workspace tests with the lockfile enforced.
21#[bake::task(name = "test")]
22fn run(
23    context: &mut Context,
24    #[bake(named, default = false, help = "Also test examples and benchmarks.")] all_targets: bool,
25) -> Result<String> {
26    run_before_test_hook(context)?;
27
28    let mut arguments = vec![
29        "test".to_owned(),
30        "--workspace".to_owned(),
31        "--locked".to_owned(),
32    ];
33    if all_targets {
34        arguments.push("--all-targets".to_owned());
35    }
36
37    cargo::run(context, &arguments)?;
38    Ok("Cargo workspace tests passed".to_owned())
39}
40
41/// Test configured downstream repositories against this workspace's local packages.
42#[bake::task(name = "test:external")]
43fn run_external(
44    context: &mut Context,
45    #[bake(named, default = false, help = "Also test examples and benchmarks.")] all_targets: bool,
46) -> Result<String> {
47    let workspace = metadata::read_workspace(context)?;
48    if workspace.external_repositories.is_empty() {
49        return Ok("No downstream repositories are configured for external tests".to_owned());
50    }
51    if workspace.packages.is_empty() {
52        return Err(Error::new(
53            "the current workspace has no crates.io packages to patch into downstream tests",
54        ));
55    }
56
57    let mut checkouts = Vec::with_capacity(workspace.external_repositories.len());
58    for repository in &workspace.external_repositories {
59        let checkout = external::checkout(context, repository)?;
60        manifest::patch_checkout(&checkout, &workspace.packages)?;
61        external::ensure_local_patches_are_selected(&checkout, &workspace.packages)?;
62        checkouts.push(checkout);
63    }
64
65    run_before_test_hook(context)?;
66
67    for checkout in &checkouts {
68        let mut arguments = vec!["test".to_owned(), "--workspace".to_owned()];
69        if all_targets {
70            arguments.push("--all-targets".to_owned());
71        }
72        external::run_cargo(checkout, &arguments)?;
73    }
74
75    let repository_count = checkouts.len();
76    let repository_label = if repository_count == 1 {
77        "repository"
78    } else {
79        "repositories"
80    };
81    Ok(format!(
82        "External tests passed for {repository_count} downstream {repository_label}"
83    ))
84}