rusty-pv 0.1.0

Pipe viewer — a Rust port of Andrew Wood's `pv(1)` with progress bar, ETA, rate display, token-bucket rate limiting, IEC/SI unit math, SIGWINCH-aware terminal redraw, SIGUSR1 size refresh, multi-instance cursor coordination, and a typed library API.
Documentation
//! US3 (Strict-compat drop-in) integration tests.

mod common;

#[test]
fn strict_unknown_flag_byte_format() {
    let assert = common::rusty_pv_cmd()
        .arg("--strict")
        .arg("-Z")
        .assert()
        .failure();
    let stderr = String::from_utf8_lossy(&assert.get_output().stderr).into_owned();
    assert!(
        stderr.contains("invalid option") && stderr.contains("'Z'"),
        "Strict unknown-flag stderr should mention the offending character; got: {stderr:?}"
    );
}

#[test]
fn strict_excluded_flag_f_rejected() {
    // FR-039 + Clarifications Q12: `-F` is upstream-supported but excluded
    // from v0.1.0; Strict parser MUST reject with upstream-style message.
    let assert = common::rusty_pv_cmd()
        .arg("--strict")
        .arg("-F")
        .arg("%p")
        .assert()
        .failure();
    let stderr = String::from_utf8_lossy(&assert.get_output().stderr).into_owned();
    assert!(
        stderr.contains("invalid option") && stderr.contains("'F'"),
        "Strict mode must reject excluded -F; got: {stderr:?}"
    );
}

#[test]
fn strict_last_wins_rate_limit() {
    // FR-040 — last-wins flag resolution.
    let assert = common::rusty_pv_cmd()
        .arg("--strict")
        .arg("-q")
        .arg("-L")
        .arg("1M")
        .arg("-L")
        .arg("100M")
        .write_stdin("x")
        .assert()
        .success();
    // We can't easily observe the rate from the outside; the success here
    // confirms the parser accepted the repeated flag without erroring.
    assert!(assert.get_output().status.success());
}

#[test]
fn strict_grouped_short_flags() {
    // FR-040 grouped short flags `-rb` = `-r -b`.
    let assert = common::rusty_pv_cmd()
        .arg("--strict")
        .arg("-q")
        .arg("-rb")
        .write_stdin("hello")
        .assert()
        .success();
    let stdout = String::from_utf8_lossy(&assert.get_output().stdout).into_owned();
    assert_eq!(stdout, "hello");
}

#[test]
fn strict_does_not_emit_completion_script() {
    // FR-041 + SC-009 — Strict treats `completions` as positional, NOT a subcommand.
    let assert = common::rusty_pv_cmd()
        .arg("--strict")
        .arg("completions")
        .arg("bash")
        .write_stdin("")
        .assert();
    let stdout = String::from_utf8_lossy(&assert.get_output().stdout).into_owned();
    assert!(
        !stdout.contains("#!/") && !stdout.contains("complete -F"),
        "Strict mode must NOT emit a completion script; got: {stdout:?}"
    );
}

#[test]
fn strict_activates_via_env_var() {
    let assert = common::rusty_pv_cmd()
        .env("RUSTY_PV_STRICT", "1")
        .arg("-q")
        .write_stdin("data")
        .assert()
        .success();
    let stdout = String::from_utf8_lossy(&assert.get_output().stdout).into_owned();
    assert_eq!(stdout, "data");
}

#[test]
fn no_strict_overrides_env() {
    // FR-038 — `--no-strict` beats the env var.
    let assert = common::rusty_pv_cmd()
        .env("RUSTY_PV_STRICT", "1")
        .arg("--no-strict")
        .arg("-q")
        .write_stdin("x")
        .assert()
        .success();
    assert_eq!(assert.get_output().stdout.as_slice(), b"x");
}