use std::process::{Command, Stdio};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ExecutionResult {
pub stdout: String,
pub stderr: String,
pub exit_code: i32,
pub success: bool,
}
impl ExecutionResult {
pub fn format(&self) -> String {
let mut output = String::new();
if !self.stdout.is_empty() {
output.push_str(&self.stdout);
if !self.stdout.ends_with('\n') {
output.push('\n');
}
}
if !self.stderr.is_empty() {
output.push_str(&self.stderr);
if !self.stderr.ends_with('\n') {
output.push('\n');
}
}
if !self.success {
output.push_str(&format!("Exit code: {}\n", self.exit_code));
}
output
}
}
pub fn execute_command(command: &str) -> ExecutionResult {
let output = Command::new("bash")
.arg("-c")
.arg(command)
.stdin(Stdio::null())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.output();
match output {
Ok(output) => {
let stdout = String::from_utf8_lossy(&output.stdout).to_string();
let stderr = String::from_utf8_lossy(&output.stderr).to_string();
let exit_code = output.status.code().unwrap_or(-1);
let success = output.status.success();
ExecutionResult {
stdout,
stderr,
exit_code,
success,
}
}
Err(e) => {
ExecutionResult {
stdout: String::new(),
stderr: format!("Failed to execute command: {}", e),
exit_code: -1,
success: false,
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_REPL_008_001_execute_echo_simple() {
let result = execute_command("echo hello");
assert!(result.success);
assert_eq!(result.stdout.trim(), "hello");
assert_eq!(result.exit_code, 0);
}
#[test]
fn test_REPL_008_001_execute_echo_multiple_words() {
let result = execute_command("echo hello world");
assert!(result.success);
assert_eq!(result.stdout.trim(), "hello world");
}
#[test]
fn test_REPL_008_001_execute_pwd() {
let result = execute_command("pwd");
assert!(result.success);
assert!(!result.stdout.is_empty());
assert!(result.stdout.contains('/'));
}
#[test]
fn test_REPL_008_001_execute_true_command() {
let result = execute_command("true");
assert!(result.success);
assert_eq!(result.exit_code, 0);
assert_eq!(result.stdout, "");
}
#[test]
fn test_REPL_008_001_execute_false_command() {
let result = execute_command("false");
assert!(!result.success);
assert_eq!(result.exit_code, 1);
}
#[test]
fn test_REPL_008_001_execute_nonexistent_command() {
let result = execute_command("nonexistent_command_xyz_12345");
assert!(!result.success);
assert!(!result.stderr.is_empty());
assert!(result.stderr.contains("not found") || result.stderr.contains("command not found"));
}
#[test]
fn test_REPL_008_001_execute_with_pipe() {
let result = execute_command("echo hello world | head -1");
assert!(result.success);
assert_eq!(result.stdout.trim(), "hello world");
}
#[test]
fn test_REPL_008_001_execute_with_error_output() {
let result = execute_command("ls /nonexistent_directory_xyz_12345");
assert!(!result.success);
assert!(!result.stderr.is_empty());
assert!(result.stderr.contains("No such file"));
}
#[test]
fn test_REPL_008_001_format_success_output() {
let result = ExecutionResult {
stdout: "hello\n".to_string(),
stderr: String::new(),
exit_code: 0,
success: true,
};
let formatted = result.format();
assert_eq!(formatted, "hello\n");
}
#[test]
fn test_REPL_008_001_format_error_output() {
let result = ExecutionResult {
stdout: String::new(),
stderr: "error message\n".to_string(),
exit_code: 1,
success: false,
};
let formatted = result.format();
assert!(formatted.contains("error message"));
assert!(formatted.contains("Exit code: 1"));
}
#[test]
fn test_REPL_008_001_format_mixed_output() {
let result = ExecutionResult {
stdout: "stdout line\n".to_string(),
stderr: "stderr line\n".to_string(),
exit_code: 2,
success: false,
};
let formatted = result.format();
assert!(formatted.contains("stdout line"));
assert!(formatted.contains("stderr line"));
assert!(formatted.contains("Exit code: 2"));
}
#[test]
fn test_REPL_008_001_execute_date_command() {
let result = execute_command("date +%Y");
assert!(result.success);
assert!(result.stdout.trim().starts_with("202")); }
#[test]
fn test_REPL_008_001_execute_empty_command() {
let result = execute_command("");
assert!(result.success); assert_eq!(result.stdout, "");
}
#[test]
fn test_REPL_008_001_execute_special_characters() {
let result = execute_command("echo 'hello!@#$%'");
assert!(result.success);
assert_eq!(result.stdout.trim(), "hello!@#$%");
}
}