use crate::ops::forc_build;
use anyhow::{bail, Result};
use clap::Parser;
use std::io::{BufRead, BufReader};
use std::process;
use std::thread;
use tracing::{error, info};
#[derive(Debug, Parser)]
pub(crate) struct Command {
pub test_name: Option<String>,
#[clap(long)]
pub cargo_test_opts: Option<String>,
#[clap(raw = true)]
pub cargo_test_args: Vec<String>,
}
pub(crate) fn exec(command: Command) -> Result<()> {
forc_build::build(Default::default())?;
let mut cmd = process::Command::new("cargo");
cmd.arg("test");
let mut user_specified_color_opt = false;
if let Some(opts) = command.cargo_test_opts {
user_specified_color_opt = opts.contains("--color");
for opt in opts.split_whitespace() {
cmd.arg(&opt);
}
}
if !user_specified_color_opt {
cmd.args(&["--color", "always"]);
}
if let Some(ref name) = command.test_name {
cmd.arg(name);
}
if !command.cargo_test_args.is_empty() {
cmd.arg("--");
cmd.args(&command.cargo_test_args);
}
let mut child = cmd
.stdout(process::Stdio::piped())
.stderr(process::Stdio::piped())
.spawn()
.unwrap();
let out = BufReader::new(child.stdout.take().unwrap());
let err = BufReader::new(child.stderr.take().unwrap());
let thread = thread::spawn(move || {
err.lines().for_each(|line| error!("{}", line.unwrap()));
});
out.lines().for_each(|line| info!("{}", line.unwrap()));
thread.join().unwrap();
let child_success = match child.try_wait() {
Ok(Some(returned_status)) => returned_status.success(),
Ok(None) => child.wait().unwrap().success(),
Err(_) => false,
};
match child_success {
true => Ok(()),
false => bail!("child test process failed"),
}
}