//! 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)
    );
}
