use ggen_utils::safe_command::SafeCommand;
use ggen_utils::safe_path::SafePath;
use std::process::Stdio;
#[test]
fn test_execute_cargo_version() {
let safe_cmd = SafeCommand::new("cargo")
.unwrap()
.arg("--version")
.unwrap()
.validate()
.unwrap();
let mut cmd = safe_cmd.into_command();
cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
let output = cmd.output();
assert!(output.is_ok(), "Should execute cargo --version");
let output = output.unwrap();
assert!(output.status.success(), "Command should succeed");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("cargo"),
"Output should contain 'cargo': {}",
stdout
);
}
#[test]
fn test_execute_git_version() {
let safe_cmd = SafeCommand::new("git")
.unwrap()
.arg("--version")
.unwrap()
.validate()
.unwrap();
let mut cmd = safe_cmd.into_command();
cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
let output = cmd.output();
assert!(output.is_ok(), "Should execute git --version");
let output = output.unwrap();
assert!(output.status.success(), "Command should succeed");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("git"),
"Output should contain 'git': {}",
stdout
);
}
#[test]
fn test_execute_rustc_version() {
let safe_cmd = SafeCommand::new("rustc")
.unwrap()
.arg("--version")
.unwrap()
.validate()
.unwrap();
let mut cmd = safe_cmd.into_command();
cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
let output = cmd.output();
assert!(output.is_ok(), "Should execute rustc --version");
let output = output.unwrap();
assert!(output.status.success(), "Command should succeed");
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("rustc"),
"Output should contain 'rustc': {}",
stdout
);
}
#[test]
#[cfg(unix)]
fn test_execute_timeout_command() {
let safe_cmd = SafeCommand::new("timeout")
.unwrap()
.arg("1s")
.unwrap()
.arg("echo")
.unwrap()
.arg("test")
.unwrap()
.validate()
.unwrap();
let mut cmd = safe_cmd.into_command();
cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
let output = cmd.output();
assert!(output.is_ok(), "Should execute timeout command");
}
#[test]
fn test_execute_invalid_arg_fails() {
let safe_cmd = SafeCommand::new("cargo")
.unwrap()
.arg("invalid-subcommand-xyz")
.unwrap()
.validate()
.unwrap();
let mut cmd = safe_cmd.into_command();
cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
let output = cmd.output();
assert!(output.is_ok(), "Command should execute (but may fail)");
let output = output.unwrap();
assert!(!output.status.success(), "Invalid subcommand should fail");
}
#[test]
#[cfg(unix)]
fn test_execute_with_safe_path() {
let safe_path = SafePath::new_absolute("/dev/null").unwrap();
let safe_cmd = SafeCommand::new("git")
.unwrap()
.arg("hash-object")
.unwrap()
.arg_path(&safe_path)
.validate()
.unwrap();
let mut cmd = safe_cmd.into_command();
cmd.stdout(Stdio::piped()).stderr(Stdio::piped());
let output = cmd.output();
assert!(output.is_ok(), "Should execute with SafePath");
let output = output.unwrap();
assert!(output.status.success(), "Command should succeed");
}
#[test]
fn test_builder_pattern_chaining() {
let result = SafeCommand::new("cargo")
.unwrap()
.arg("build")
.unwrap()
.arg("--release")
.unwrap()
.arg("--all-features")
.unwrap()
.validate();
assert!(result.is_ok(), "Builder pattern should chain correctly");
let cmd = result.unwrap();
assert_eq!(
cmd.to_string_debug(),
"cargo build --release --all-features"
);
}
#[test]
fn test_builder_pattern_with_args_bulk() {
let result = SafeCommand::new("cargo")
.unwrap()
.args(["build", "--release", "--all-features"])
.unwrap()
.validate();
assert!(result.is_ok(), "Bulk args should work");
let cmd = result.unwrap();
assert_eq!(
cmd.to_string_debug(),
"cargo build --release --all-features"
);
}
#[test]
fn test_builder_pattern_mixed_arg_types() {
let path = SafePath::new("src/main.rs").unwrap();
let result = SafeCommand::new("rustfmt")
.unwrap()
.arg("--check")
.unwrap()
.arg_path(&path)
.validate();
assert!(result.is_ok(), "Mixed arg types should work");
let cmd = result.unwrap();
let debug_str = cmd.to_string_debug();
assert!(debug_str.contains("rustfmt"));
assert!(debug_str.contains("--check"));
assert!(debug_str.contains("src/main.rs"));
}
#[test]
fn test_type_state_unvalidated_to_validated() {
let unvalidated = SafeCommand::new("cargo").unwrap().arg("build").unwrap();
let validated = unvalidated.validate();
assert!(validated.is_ok(), "Should transition to validated state");
}
#[test]
fn test_type_state_validated_has_accessors() {
let validated = SafeCommand::new("cargo")
.unwrap()
.arg("build")
.unwrap()
.validate()
.unwrap();
let command = validated.command();
let args = validated.args();
let debug_str = validated.to_string_debug();
assert_eq!(command.as_str(), "cargo");
assert_eq!(args.len(), 1);
assert_eq!(args[0].as_str(), "build");
assert_eq!(debug_str, "cargo build");
}