car-server-core 0.36.0

Transport-neutral library for the CAR daemon JSON-RPC dispatcher (used by car-server and tokhn-daemon)
//! Cross-platform shell-check command builders for coder tests.
//!
//! The coder runs a check / goal command through its shell tool — `sh -lc` on
//! Unix, `cmd /C` on Windows — so a test fixture must not hard-code POSIX-only
//! commands (`grep`, `true`, `false`, `cat`, `test -f`); those fail with
//! `'grep' is not recognized` on Windows and take the whole scripted loop with
//! them. Each builder emits the shell-appropriate equivalent for the current
//! target so the same fixture verifies identically on every OS.
#![cfg(test)]

/// Absolute path to a Windows System32 utility, for commands that are NOT `cmd`
/// builtins.
///
/// **Do not shorten these to a bare program name.** `PATH` on a Windows box is
/// not guaranteed to contain `C:\Windows\System32` — the GitHub `windows-latest`
/// runner is one that doesn't. `cmd.exe` itself still launches there, because
/// Windows' `CreateProcess` falls back to the system directory when resolving a
/// program name, but `cmd`'s *own* lookup for an external command consults only
/// `%PATH%` — so a bare `findstr` / `ping` dies with "'findstr' is not
/// recognized" while every builtin (`exit`, `if exist`, `type`) works fine. That
/// asymmetry is exactly what broke these fixtures in CI while they passed
/// locally. `%SystemRoot%` is expanded by `cmd`, so this needs no PATH lookup.
///
/// Defined unconditionally (not `#[cfg(windows)]`) because the callers select
/// with a runtime `cfg!(windows)`, so the call is compiled on every platform.
fn system32(exe: &str) -> String {
    format!("%SystemRoot%\\System32\\{exe}")
}

/// A command that always succeeds (exit 0). `exit` is a builtin of both `sh`
/// and `cmd`, so this literal is portable — no per-OS branch needed.
pub(crate) const PASS: &str = "exit 0";

/// A command that always fails (exit 1). Portable for the same reason as
/// [`PASS`].
pub(crate) const FAIL: &str = "exit 1";

/// Succeeds iff `file` exists — POSIX `test -f`, cmd `if exist`.
pub(crate) fn file_exists(file: &str) -> String {
    if cfg!(windows) {
        format!("if exist {file} (exit 0) else (exit 1)")
    } else {
        format!("test -f {file}")
    }
}

/// Prints the contents of `file` — POSIX `cat`, cmd `type`. Pair with a
/// `output_contains` assertion for a content check that streams the file.
pub(crate) fn cat(file: &str) -> String {
    if cfg!(windows) {
        format!("type {file}")
    } else {
        format!("cat {file}")
    }
}

/// Succeeds iff `file` contains the literal `needle` — POSIX `grep`, cmd
/// `findstr`. Case-sensitive on both (matching `grep -q`, not `grep -qi`).
///
/// **`needle` must be a single whitespace-free token.** The command is handed to
/// `cmd /C <arg>` on Windows, and a quoted `findstr /C:"…"` can't survive that
/// round-trip — Rust re-quotes the whole arg and `cmd` mangles the inner quotes
/// (`FINDSTR: Cannot open …`). A bare, unquoted findstr search string is a
/// single literal token, so fixtures pick one distinctive word of the expected
/// content instead of the whole phrase.
pub(crate) fn contains(needle: &str, file: &str) -> String {
    debug_assert!(
        !needle.chars().any(char::is_whitespace),
        "contains() needle must be a single whitespace-free token; got {needle:?}"
    );
    if cfg!(windows) {
        format!("{} {needle} {file}", system32("findstr.exe"))
    } else {
        format!("grep -qF {needle} {file}")
    }
}

/// Like [`contains`], but on failure prints `assertion failed` before exiting
/// non-zero. A failing check's output feeds the repair-learning failure
/// signature, so the fixture needs a stable, recognizable failure message on
/// both shells — not just findstr/grep's silent exit code.
pub(crate) fn contains_or_report(needle: &str, file: &str) -> String {
    debug_assert!(
        !needle.chars().any(char::is_whitespace),
        "contains_or_report() needle must be a single token; got {needle:?}"
    );
    if cfg!(windows) {
        format!(
            "{} {needle} {file} || (echo assertion failed & exit 1)",
            system32("findstr.exe")
        )
    } else {
        format!("grep -qF {needle} {file} || {{ echo 'assertion failed'; exit 1; }}")
    }
}

/// Creates (or touches) an empty `file` — POSIX `touch`, cmd `type nul >`.
/// Used by goal fixtures whose scripted model "creates a file", where the
/// deterministic goal check then asserts the file exists on disk.
pub(crate) fn touch(file: &str) -> String {
    if cfg!(windows) {
        format!("type nul > {file}")
    } else {
        format!("touch {file}")
    }
}

/// Prints the working directory — POSIX `pwd`, cmd `cd` (with no argument, `cd`
/// echoes the current directory rather than changing it).
pub(crate) fn print_cwd() -> String {
    if cfg!(windows) { "cd" } else { "pwd" }.to_string()
}

/// A command that blocks for roughly `secs` seconds without needing a console or
/// stdin — POSIX `sleep`, Windows `ping` loopback delay (`timeout` refuses a
/// redirected stdin, which the coder shell always supplies). Used by cancel /
/// timeout fixtures that need a long-running child to interrupt.
pub(crate) fn sleep(secs: u32) -> String {
    if cfg!(windows) {
        // ping waits ~1s between echoes; N+1 pings ≈ N seconds. `>nul` mutes it.
        format!("{} -n {} 127.0.0.1 >nul", system32("ping.exe"), secs + 1)
    } else {
        format!("sleep {secs}")
    }
}