use std::process::{Command, Output};
use std::sync::mpsc;
use std::thread;
use std::time::Duration;
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(5);
pub fn run_command_with_timeout(cmd: &str, args: &[&str], timeout: Duration) -> Option<Output> {
let cmd_owned = cmd.to_string();
let args_owned: Vec<String> = args.iter().map(|s| (*s).to_string()).collect();
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
let output = Command::new(&cmd_owned).args(&args_owned).output();
let _ = tx.send(output);
});
match rx.recv_timeout(timeout) {
Ok(Ok(output)) => Some(output),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_run_command_with_timeout_success() {
let result = run_command_with_timeout("echo", &["hello"], DEFAULT_TIMEOUT);
assert!(result.is_some());
let output = result.unwrap();
assert!(output.status.success());
}
#[test]
fn test_run_command_with_timeout_nonexistent() {
let result =
run_command_with_timeout("nonexistent_command_12345", &[], Duration::from_millis(100));
if let Some(output) = result {
assert!(!output.status.success());
}
}
}