169 lines
6.1 KiB
Rust
169 lines
6.1 KiB
Rust
#[cfg(test)]
|
|
mod tests {
|
|
use std::sync::{Arc, Mutex};
|
|
use std::thread;
|
|
use std::time::Duration;
|
|
use crate::process::run::{run, RunError};
|
|
use crate::text::dedent;
|
|
|
|
#[test]
|
|
fn test_run_command() {
|
|
// Test running a simple echo command using the builder pattern
|
|
let result = run("echo hello").execute().unwrap();
|
|
assert!(result.success);
|
|
assert_eq!(result.code, 0);
|
|
assert!(result.stdout.trim().contains("hello"));
|
|
assert_eq!(result.stderr, "");
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_silent_command() {
|
|
// Test running a command silently using the builder pattern
|
|
let result = run("echo silent test").silent(true).execute().unwrap();
|
|
assert!(result.success);
|
|
assert_eq!(result.code, 0);
|
|
assert!(result.stdout.trim().contains("silent test"));
|
|
assert_eq!(result.stderr, "");
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_script() {
|
|
// Test running a multi-line script using the builder pattern
|
|
let script = r#"
|
|
echo "line 1"
|
|
echo "line 2"
|
|
"#;
|
|
|
|
let result = run(script).execute().unwrap();
|
|
assert!(result.success);
|
|
assert_eq!(result.code, 0);
|
|
assert!(result.stdout.contains("line 1"));
|
|
assert!(result.stdout.contains("line 2"));
|
|
assert_eq!(result.stderr, "");
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_with_dedent() {
|
|
// Test that run properly dedents scripts
|
|
let script = r#"
|
|
echo "This has 12 spaces of indentation"
|
|
echo "This has 16 spaces (4 more than the common indentation)"
|
|
"#;
|
|
|
|
// The dedent function should remove the common 12 spaces
|
|
let dedented = dedent(script);
|
|
assert!(dedented.contains("echo \"This has 12 spaces of indentation\""));
|
|
assert!(dedented.contains(" echo \"This has 16 spaces (4 more than the common indentation)\""));
|
|
|
|
// Running the script should work with the dedented content
|
|
let result = run(script).execute().unwrap();
|
|
assert!(result.success);
|
|
assert_eq!(result.code, 0);
|
|
assert!(result.stdout.contains("This has 12 spaces of indentation"));
|
|
assert!(result.stdout.contains("This has 16 spaces (4 more than the common indentation)"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_detects_script_vs_command() {
|
|
// Test that run correctly identifies scripts vs commands
|
|
|
|
// One-liner should be treated as a command
|
|
let one_liner = "echo one-liner test";
|
|
let result = run(one_liner).execute().unwrap();
|
|
assert!(result.success);
|
|
assert!(result.stdout.contains("one-liner test"));
|
|
|
|
// Multi-line input should be treated as a script
|
|
let multi_line = "echo first line\necho second line";
|
|
let result = run(multi_line).execute().unwrap();
|
|
assert!(result.success);
|
|
assert!(result.stdout.contains("first line"));
|
|
assert!(result.stdout.contains("second line"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_empty_command() {
|
|
// Test handling of empty commands
|
|
let result = run("").execute();
|
|
assert!(result.is_err());
|
|
// The specific error should be EmptyCommand
|
|
match result {
|
|
Err(RunError::EmptyCommand) => (),
|
|
_ => panic!("Expected EmptyCommand error"),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_die_option() {
|
|
// Test the die option - when false, it should return a CommandResult with success=false
|
|
// instead of an Err when the command fails
|
|
|
|
// With die=true (default), a non-existent command should return an error
|
|
let result = run("non_existent_command").execute();
|
|
assert!(result.is_err());
|
|
|
|
// With die=false, it should return a CommandResult with success=false
|
|
let result = run("non_existent_command").die(false).execute().unwrap();
|
|
assert!(!result.success);
|
|
assert_ne!(result.code, 0);
|
|
assert!(result.stderr.contains("Error:"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_async_option() {
|
|
// Test the async option - when true, it should spawn the process and return immediately
|
|
|
|
// Create a shared variable to track if the command has completed
|
|
let completed = Arc::new(Mutex::new(false));
|
|
let completed_clone = completed.clone();
|
|
|
|
// Run a command that sleeps for 2 seconds, with async=true
|
|
let start = std::time::Instant::now();
|
|
let result = run("sleep 2").async_exec(true).execute().unwrap();
|
|
let elapsed = start.elapsed();
|
|
|
|
// The command should return immediately (much less than 2 seconds)
|
|
assert!(elapsed < Duration::from_secs(1));
|
|
|
|
// The result should have empty stdout/stderr and success=true
|
|
assert!(result.success);
|
|
assert_eq!(result.code, 0);
|
|
assert_eq!(result.stdout, "");
|
|
assert_eq!(result.stderr, "");
|
|
|
|
// Wait a bit to ensure the command has time to complete
|
|
thread::sleep(Duration::from_secs(3));
|
|
|
|
// Verify the command completed (this is just a placeholder since we can't easily
|
|
// check if the async command completed in this test framework)
|
|
*completed_clone.lock().unwrap() = true;
|
|
assert!(*completed.lock().unwrap());
|
|
}
|
|
|
|
#[test]
|
|
fn test_run_log_option() {
|
|
// Test the log option - when true, it should log command execution
|
|
// Note: We can't easily capture stdout in tests, so this is more of a smoke test
|
|
|
|
// Run a command with log=true
|
|
let result = run("echo log test").log(true).execute().unwrap();
|
|
assert!(result.success);
|
|
assert_eq!(result.code, 0);
|
|
assert!(result.stdout.trim().contains("log test"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_builder_method_chaining() {
|
|
// Test that all builder methods can be chained together
|
|
let result = run("echo chaining test")
|
|
.silent(true)
|
|
.die(true)
|
|
.log(true)
|
|
.execute()
|
|
.unwrap();
|
|
|
|
assert!(result.success);
|
|
assert_eq!(result.code, 0);
|
|
assert!(result.stdout.trim().contains("chaining test"));
|
|
}
|
|
} |