diff --git a/nash/tests/stdin.rs b/nash/tests/stdin.rs new file mode 100644 index 0000000..52295c3 --- /dev/null +++ b/nash/tests/stdin.rs @@ -0,0 +1,74 @@ +//! End-to-end tests for scripts supplied through `nash -s` on standard input. + +use std::io::Write; +use std::process::{Command, Output, Stdio}; + +fn run_stdin(script: &str) -> Output { + let mut child = Command::new(env!("CARGO_BIN_EXE_nash")) + .args(["--noprofile", "--norc", "-s"]) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .expect("spawn nash"); + + child + .stdin + .take() + .expect("piped stdin") + .write_all(script.as_bytes()) + .expect("write script"); + + child.wait_with_output().expect("wait for nash") +} + +#[test] +fn multiline_compound_commands_execute_from_stdin() { + let output = run_stdin( + r#"greet() { + case "$1" in + world) + cat <<'EOF' +hello world +EOF + ;; + *) + echo unexpected + ;; + esac +} +greet world +"#, + ); + + assert!( + output.status.success(), + "nash failed: {}", + String::from_utf8_lossy(&output.stderr) + ); + assert_eq!(String::from_utf8_lossy(&output.stdout), "hello world\n"); +} + +#[test] +fn commands_can_consume_following_stdin() { + let output = run_stdin("read value\npayload\necho got:$value\n"); + + assert!( + output.status.success(), + "nash failed: {}", + String::from_utf8_lossy(&output.stderr) + ); + assert_eq!(String::from_utf8_lossy(&output.stdout), "got:payload\n"); +} + +#[test] +fn incomplete_stdin_command_reports_a_parse_error() { + let output = run_stdin("if true; then\n echo never\n"); + + assert!(!output.status.success()); + assert!( + String::from_utf8_lossy(&output.stderr).contains("syntax error at end of input"), + "unexpected stderr: {}", + String::from_utf8_lossy(&output.stderr) + ); +}