Skip to main content

cargo_zigbuild/
test.rs

1use std::ops::{Deref, DerefMut};
2use std::path::PathBuf;
3use std::process::{self, Command};
4
5use anyhow::{Context, Result};
6use clap::Parser;
7
8use crate::Zig;
9
10/// Execute all unit and integration tests and build examples of a local package
11#[derive(Clone, Debug, Default, Parser)]
12#[command(
13    display_order = 1,
14    after_help = "Run `cargo help test` for more detailed information.\nRun `cargo test -- --help` for test binary options."
15)]
16pub struct Test {
17    /// Disable zig linker
18    #[arg(skip)]
19    pub disable_zig_linker: bool,
20
21    /// Enable zig ar
22    #[arg(skip)]
23    pub enable_zig_ar: bool,
24
25    /// Minimum macOS version, overrides `MACOSX_DEPLOYMENT_TARGET`
26    #[arg(skip)]
27    pub macosx_deployment_target: Option<String>,
28
29    #[command(flatten)]
30    pub cargo: cargo_options::Test,
31}
32
33impl Test {
34    /// Create a new test from manifest path
35    #[allow(clippy::field_reassign_with_default)]
36    pub fn new(manifest_path: Option<PathBuf>) -> Self {
37        let mut build = Self::default();
38        build.manifest_path = manifest_path;
39        build
40    }
41
42    /// Execute `cargo test` command
43    pub fn execute(&self) -> Result<()> {
44        let mut test = self.build_command()?;
45
46        let mut child = test.spawn().context("Failed to run cargo test")?;
47        let status = child.wait().expect("Failed to wait on cargo test process");
48        if !status.success() {
49            process::exit(status.code().unwrap_or(1));
50        }
51        Ok(())
52    }
53
54    /// Generate cargo subcommand
55    pub fn build_command(&self) -> Result<Command> {
56        let mut build = self.cargo.command();
57        if !self.disable_zig_linker {
58            Zig::apply_command_env(
59                self.manifest_path.as_deref(),
60                self.release,
61                &self.cargo.common,
62                &mut build,
63                self.enable_zig_ar,
64                self.macosx_deployment_target.as_deref(),
65            )?;
66        }
67
68        Ok(build)
69    }
70}
71
72impl Deref for Test {
73    type Target = cargo_options::Test;
74
75    fn deref(&self) -> &Self::Target {
76        &self.cargo
77    }
78}
79
80impl DerefMut for Test {
81    fn deref_mut(&mut self) -> &mut Self::Target {
82        &mut self.cargo
83    }
84}
85
86impl From<cargo_options::Test> for Test {
87    fn from(cargo: cargo_options::Test) -> Self {
88        Self {
89            cargo,
90            ..Default::default()
91        }
92    }
93}