smcp_computer/inputs/
utils.rs1use crate::errors::ComputerError;
12use std::process::Command;
13
14pub async fn run_command(command: &str, args: &[String]) -> Result<String, ComputerError> {
38 let output = if cfg!(target_os = "windows") {
39 let mut cmd = Command::new("cmd");
41 cmd.arg("/C");
42 cmd.arg(command);
43 for arg in args {
44 cmd.arg(arg);
45 }
46 cmd.output()
47 } else {
48 let mut cmd = Command::new("sh");
50 cmd.arg("-c");
51 let shell_cmd = if args.is_empty() {
53 command.to_string()
54 } else {
55 format!("{} {}", command, args.join(" "))
56 };
57 cmd.arg(&shell_cmd);
58 cmd.output()
59 }
60 .map_err(|e| ComputerError::RuntimeError(format!("Command execution failed: {}", e)))?;
61
62 if !output.status.success() {
63 let stderr = String::from_utf8_lossy(&output.stderr);
64 return Err(ComputerError::RuntimeError(format!(
65 "Command failed with exit code {}: {}",
66 output.status.code().unwrap_or(-1),
67 stderr
68 )));
69 }
70
71 Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
72}
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77
78 #[tokio::test]
79 async fn test_run_command_simple() {
80 let output = run_command("echo", &["hello".to_string()]).await.unwrap();
81 assert_eq!(output, "hello");
82 }
83
84 #[tokio::test]
85 async fn test_run_command_no_args() {
86 let output = run_command("pwd", &[]).await.unwrap();
87 assert!(!output.is_empty());
89 }
90
91 #[tokio::test]
92 async fn test_run_command_failure() {
93 let result = run_command("nonexistent_command", &[]).await;
94 assert!(result.is_err());
95 }
96}