use super::Pipeline;
use crate::cmd;
use crate::cmd::PipeMode;
#[test]
fn test_pipeline() {
let output = cmd!("echo", "hello")
.pipe(cmd!("tr", "[:lower:]", "[:upper:]"))
.no_echo()
.output()
.unwrap();
assert_eq!(output.trim(), "HELLO");
}
#[test]
fn test_pipeline_with_input() {
let output = cmd!("tr", "[:lower:]", "[:upper:]")
.input("hello world")
.no_echo()
.output()
.unwrap();
assert_eq!(output.trim(), "HELLO WORLD");
}
#[test]
fn test_multiple_pipes() {
let output = cmd!("echo", "hello world")
.pipe(cmd!("tr", "[:lower:]", "[:upper:]"))
.pipe(cmd!("rev"))
.no_echo()
.output()
.unwrap();
assert_eq!(output.trim(), "DLROW OLLEH");
}
#[test]
fn test_pipe_err() {
let output = cmd!("sh", "-c", "echo 'error message' >&2")
.pipe_err(cmd!("wc", "-c"))
.no_echo()
.output()
.unwrap();
assert_eq!(output.trim(), "14");
}
#[test]
fn test_pipe_out_err() {
let output = cmd!("sh", "-c", "echo 'stdout' && echo 'stderr' >&2")
.pipe_out_err(cmd!("sort"))
.no_echo()
.output()
.unwrap();
let lines: Vec<&str> = output.trim().lines().collect();
assert_eq!(lines.len(), 2);
assert!(lines.contains(&"stdout"));
assert!(lines.contains(&"stderr"));
assert_eq!(lines[0], "stderr");
assert_eq!(lines[1], "stdout");
}
#[test]
fn test_default_pipe_mode() {
let pipeline = cmd!("echo", "test").pipe(cmd!("cat"));
assert_eq!(pipeline.connections[1].1, PipeMode::Stdout);
}
#[test]
fn test_pipe_err_mode() {
let pipeline = cmd!("echo", "test").pipe_err(cmd!("cat"));
assert_eq!(pipeline.connections[1].1, PipeMode::Stderr);
}
#[test]
fn test_pipe_out_err_mode() {
let pipeline = cmd!("echo", "test").pipe_out_err(cmd!("cat"));
assert_eq!(pipeline.connections[1].1, PipeMode::Both);
}
#[test]
fn test_direct_pipe_methods() {
let stdout_result = cmd!("echo", "native test")
.pipe(cmd!("cat"))
.no_echo()
.output()
.unwrap();
assert_eq!(stdout_result.trim(), "native test");
let stderr_result = cmd!("sh", "-c", "echo 'native error' >&2")
.pipe_err(cmd!("wc", "-c"))
.no_echo()
.output()
.unwrap();
assert_eq!(stderr_result.trim(), "13");
let both_result = cmd!("sh", "-c", "echo 'out'; echo 'err' >&2")
.pipe_out_err(cmd!("wc", "-l"))
.no_echo()
.output()
.unwrap();
assert_eq!(both_result.trim(), "2");
}
#[test]
fn test_complex_mixed_pipeline() {
let output = cmd!("sh", "-c", "echo 'normal output'; echo 'error output' >&2")
.pipe_err(cmd!("sed", "s/error/processed_error/"))
.pipe(cmd!("tr", "[:lower:]", "[:upper:]"))
.pipe_out_err(cmd!("sort"))
.no_echo()
.output()
.unwrap();
assert!(output.contains("PROCESSED_ERROR OUTPUT"));
assert!(!output.contains("error output")); }
#[test]
fn test_mixed_pipe_modes() {
let output = cmd!("sh", "-c", "echo 'stdout line'; echo 'stderr line' >&2")
.pipe_err(cmd!(
"sh",
"-c",
"read line; echo \"processed: $line\"; echo \"more stderr\" >&2"
))
.pipe(cmd!("wc", "-c"))
.no_echo()
.output()
.unwrap();
let char_count: i32 = output.trim().parse().unwrap();
assert_eq!(char_count, 23); }
#[test]
fn test_mixed_stderr_to_stdout_pipeline() {
let output = cmd!("sh", "-c", "echo 'error message' >&2")
.pipe_err(cmd!("wc", "-c")) .pipe(cmd!("cat")) .no_echo()
.output()
.unwrap();
assert!(output.trim().parse::<i32>().unwrap() > 0);
}
#[test]
fn test_stdout_stderr_both_sequence() {
let output = cmd!("echo", "test data")
.pipe(cmd!(
"sh",
"-c",
"read input; echo \"$input\"; echo \"error: $input\" >&2"
))
.pipe_err(cmd!("sed", "s/^/ERR: /"))
.pipe_out_err(cmd!("wc", "-l"))
.no_echo()
.output()
.unwrap();
assert_eq!(output.trim(), "1");
}
#[test]
fn test_alternating_pipe_modes() {
let output = cmd!("sh", "-c", "echo 'line1'; echo 'err1' >&2")
.pipe_err(cmd!("tr", "[:lower:]", "[:upper:]"))
.no_echo()
.output()
.unwrap();
let output_str = output.trim();
assert_eq!(output_str, "ERR1");
}
#[test]
fn test_long_mixed_pipeline() {
let output = cmd!("echo", "start")
.pipe(cmd!(
"sh",
"-c",
"read input; echo \"$input-processed\"; echo \"warning\" >&2"
))
.pipe_err(cmd!("wc", "-c"))
.pipe(cmd!("sh", "-c", "read count; echo \"chars: $count\""))
.pipe_out_err(cmd!("wc", "-w"))
.no_echo()
.output()
.unwrap();
assert!(output.trim().parse::<i32>().unwrap() >= 1);
}
#[test]
fn test_pipeline_single_command() {
let output = cmd!("echo", "single").no_echo().output().unwrap();
assert_eq!(output.trim(), "single");
}
#[test]
fn test_pipeline_input_override() {
let output = cmd!("cat")
.input("original")
.pipe(cmd!("tr", "[:lower:]", "[:upper:]"))
.input("pipeline_input")
.no_echo()
.output()
.unwrap();
assert_eq!(output.trim(), "PIPELINE_INPUT");
}
#[test]
fn test_very_long_pipeline() {
let output = cmd!("echo", "start")
.pipe(cmd!("sed", "s/^/step0_/"))
.pipe(cmd!("sed", "s/^/step1_/"))
.pipe(cmd!("sed", "s/^/step2_/"))
.pipe(cmd!("sed", "s/^/step3_/"))
.pipe(cmd!("sed", "s/^/step4_/"))
.no_echo()
.output()
.unwrap();
assert!(output.contains("step4_step3_step2_step1_step0_start"));
}
#[test]
fn test_pipe_mode_combinations() {
let output = cmd!("sh", "-c", "echo 'out1'; echo 'err1' >&2")
.pipe_err(cmd!(
"sh",
"-c",
"read line; echo \"stderr_to_stdout: $line\"; echo 'err2' >&2"
))
.pipe_out_err(cmd!(
"sh",
"-c",
"while read line; do echo \"combined: $line\"; done"
))
.pipe(cmd!("wc", "-l"))
.no_echo()
.output()
.unwrap();
let line_count: i32 = output.trim().parse().unwrap();
assert!(line_count >= 1);
}
#[test]
fn test_empty_pipeline() {
let pipeline = Pipeline {
connections: vec![],
input: None,
suppress_echo: true,
};
let result = pipeline.output().unwrap();
assert!(result.is_empty());
}
#[test]
fn test_pipeline_error_scenarios() {
let result = cmd!("nonexistent_command_xyz")
.pipe(cmd!("cat"))
.no_echo()
.output();
assert!(result.is_err());
let result = cmd!("echo", "test")
.pipe(cmd!("nonexistent_filter"))
.pipe(cmd!("cat"))
.no_echo()
.output();
assert!(result.is_err());
let result = cmd!("echo", "test")
.pipe(cmd!("cat"))
.pipe(cmd!("nonexistent_output"))
.no_echo()
.output();
assert!(result.is_err());
}
#[test]
fn test_pipeline_data_flow() {
let output = cmd!("echo", "hello world")
.pipe(cmd!("tr", " ", "_")) .pipe(cmd!("tr", "[:lower:]", "[:upper:]")) .pipe(cmd!("sed", "s/HELLO/GREETING/")) .no_echo()
.output()
.unwrap();
assert_eq!(output.trim(), "GREETING_WORLD");
let output = cmd!("printf", "1\n2\n3\n4\n5")
.pipe(cmd!("grep", "[13]")) .pipe(cmd!("wc", "-l")) .no_echo()
.output()
.unwrap();
assert_eq!(output.trim(), "2");
}
#[test]
fn test_stderr_pipe_data_integrity() {
let output = cmd!("sh", "-c", "echo 'ERROR: file not found' >&2")
.pipe_err(cmd!("sed", "s/ERROR:/WARNING:/"))
.pipe(cmd!("tr", "[:lower:]", "[:upper:]"))
.no_echo()
.output()
.unwrap();
assert_eq!(output.trim(), "WARNING: FILE NOT FOUND");
let output = cmd!("sh", "-c", "printf 'exactly25characters123' >&2")
.pipe_err(cmd!("wc", "-c"))
.no_echo()
.output()
.unwrap();
assert_eq!(output.trim(), "22"); }
#[test]
fn test_pipe_out_err_mixed_output() {
let output = cmd!("sh", "-c", "echo 'OUT:message1'; echo 'ERR:message2' >&2")
.pipe_out_err(cmd!("sort")) .no_echo()
.output()
.unwrap();
let lines: Vec<&str> = output.trim().lines().collect();
assert_eq!(lines.len(), 2);
assert!(lines.contains(&"ERR:message2"));
assert!(lines.contains(&"OUT:message1"));
assert_eq!(lines[0], "ERR:message2");
assert_eq!(lines[1], "OUT:message1");
}