07ba20a991
`aura --help` and `aura -h` are a newcomer's reflex first command, but today they hit the unknown-subcommand error path: exit 2, empty stdout, one-line `aura: usage: aura run` on stderr. For a C22 "newcomer sees a populated trace" milestone the conventional help affordance returning the error path is a first-contact friction. This compile-clean RED pins the desired success-path contract: `--help` and `-h` print non-empty usage to stdout and exit 0, and the usage names the `run` subcommand. A negative-preservation assertion keeps an unknown subcommand (`frobnicate`) on the exit-2 error path so the fix cannot regress bad-args handling. Asserts structural facts only (exit code, non-empty stdout, mentions `run`), not exact help prose. refs #20
69 lines
3.1 KiB
Rust
69 lines
3.1 KiB
Rust
//! Integration test: drive the built `aura` binary as a downstream user would,
|
|
//! asserting the `run` subcommand's stdout/exit contract and the bad-args path.
|
|
|
|
use std::process::Command;
|
|
|
|
/// Path to the freshly-built `aura` binary (Cargo sets this env var for the test
|
|
/// crate; the binary is named `aura` in `Cargo.toml`).
|
|
const BIN: &str = env!("CARGO_BIN_EXE_aura");
|
|
|
|
#[test]
|
|
fn run_prints_json_and_exits_zero() {
|
|
let out = Command::new(BIN).arg("run").output().expect("spawn aura run");
|
|
assert!(out.status.success(), "exit status: {:?}", out.status);
|
|
|
|
let stdout = String::from_utf8(out.stdout).expect("utf-8 stdout");
|
|
// exactly one line (the JSON object + a trailing newline from println!).
|
|
assert_eq!(stdout.lines().count(), 1, "stdout was: {stdout:?}");
|
|
let line = stdout.trim_end();
|
|
|
|
// canonical cycle-0009 JSON shape: nested manifest + metrics, stable keys.
|
|
assert!(line.starts_with("{\"manifest\":{\"commit\":\"unknown\","), "got: {line}");
|
|
assert!(line.contains("\"broker\":\"sim-optimal(pip_size=0.0001)\""), "got: {line}");
|
|
assert!(line.contains("\"window\":[1,7]"), "got: {line}");
|
|
assert!(line.contains("\"metrics\":{\"total_pips\":"), "got: {line}");
|
|
// the integer sign-flip count is stable across float renderings.
|
|
assert!(line.ends_with("\"exposure_sign_flips\":1}}"), "got: {line}");
|
|
}
|
|
|
|
#[test]
|
|
fn no_args_prints_usage_and_exits_two() {
|
|
let out = Command::new(BIN).output().expect("spawn aura");
|
|
assert_eq!(out.status.code(), Some(2), "exit status: {:?}", out.status);
|
|
assert!(out.stdout.is_empty(), "stdout should be empty on the usage path");
|
|
let stderr = String::from_utf8(out.stderr).expect("utf-8 stderr");
|
|
assert!(stderr.contains("usage"), "stderr was: {stderr:?}");
|
|
}
|
|
|
|
/// Property: `--help`/`-h` is the success-path help affordance, not the error
|
|
/// path. A newcomer's reflex first command (C22 first-contact ergonomics, #20)
|
|
/// prints the usage to stdout and exits 0; the conventional `-h` alias behaves
|
|
/// identically. An *unknown* subcommand keeps the error path (exit 2) so the
|
|
/// help fix does not regress bad-args handling.
|
|
#[test]
|
|
fn help_flag_prints_usage_to_stdout_and_exits_zero() {
|
|
for flag in ["--help", "-h"] {
|
|
let out = Command::new(BIN).arg(flag).output().expect("spawn aura --help");
|
|
assert_eq!(out.status.code(), Some(0), "`aura {flag}` exit: {:?}", out.status);
|
|
let stdout = String::from_utf8(out.stdout).expect("utf-8 stdout");
|
|
assert!(
|
|
!stdout.trim().is_empty(),
|
|
"`aura {flag}` should print help to stdout, got: {stdout:?}"
|
|
);
|
|
// The usage names the only subcommand a newcomer can run.
|
|
assert!(
|
|
stdout.contains("run"),
|
|
"`aura {flag}` help should mention the `run` subcommand, got: {stdout:?}"
|
|
);
|
|
}
|
|
|
|
// Negative-preservation: an unknown subcommand is still the error path.
|
|
let out = Command::new(BIN).arg("frobnicate").output().expect("spawn aura frobnicate");
|
|
assert_eq!(
|
|
out.status.code(),
|
|
Some(2),
|
|
"unknown subcommand must stay exit 2: {:?}",
|
|
out.status
|
|
);
|
|
}
|