From 409b770ac6ea10117cc74021732ed6720c5d39e5 Mon Sep 17 00:00:00 2001 From: Brummel Date: Fri, 5 Jun 2026 00:17:10 +0200 Subject: [PATCH] test(aura-cli): RED for strict `aura run` arg-parse `aura run extra-garbage` keys only on the first token being `run` and ignores the rest, so it prints the full report and exits 0 -- a typo'd `aura run --sweep` masquerades as a successful run instead of getting a hint. The 0010 cycle_scope ("any other or missing subcommand -> usage + exit 2") did not unambiguously cover `run `; #16 ratifies the strict reading. This RED pins it: a trailing unexpected token takes the error path (usage on stderr, empty stdout, exit 2), mirroring the no-args sibling; bare `aura run` is held to its current happy path (JSON on stdout, exit 0) by a positive-preservation assertion so the strict guard cannot regress it. refs #16 --- crates/aura-cli/tests/cli_run.rs | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/crates/aura-cli/tests/cli_run.rs b/crates/aura-cli/tests/cli_run.rs index 012d290..698ace8 100644 --- a/crates/aura-cli/tests/cli_run.rs +++ b/crates/aura-cli/tests/cli_run.rs @@ -76,6 +76,50 @@ fn run_manifest_commit_carries_real_git_head() { ); } +/// Property: `aura run` is strict about its argument vector — a trailing +/// unexpected token (e.g. a typo'd flag like `aura run --sweep`) takes the +/// error path (usage on stderr, exit 2), never a silent full run. This is the +/// strict reading ratified in #16: keying only on the first token being `run` +/// and ignoring the rest would let a typo masquerade as a successful run. +/// The same test pins positive-preservation — bare `aura run` still emits the +/// JSON report on stdout and exits 0 — so the strict guard cannot regress the +/// happy path. +#[test] +fn run_with_trailing_token_is_strict_and_exits_two() { + // Negative: an unexpected trailing token is rejected like a bad-args call. + let out = Command::new(BIN) + .args(["run", "extra-garbage"]) + .output() + .expect("spawn aura run extra-garbage"); + assert_eq!( + out.status.code(), + Some(2), + "`aura run extra-garbage` must reject the trailing token: {:?}", + out.status + ); + assert!( + out.stdout.is_empty(), + "stdout should be empty on the usage path, got: {:?}", + String::from_utf8_lossy(&out.stdout) + ); + let stderr = String::from_utf8(out.stderr).expect("utf-8 stderr"); + assert!(stderr.contains("usage"), "stderr was: {stderr:?}"); + + // Positive-preservation: bare `aura run` still runs and prints the report. + let ok = Command::new(BIN).arg("run").output().expect("spawn aura run"); + assert_eq!( + ok.status.code(), + Some(0), + "bare `aura run` must still succeed: {:?}", + ok.status + ); + let ok_stdout = String::from_utf8(ok.stdout).expect("utf-8 stdout"); + assert!( + ok_stdout.trim_start().starts_with("{\"manifest\":"), + "bare `aura run` should print the JSON report, got: {ok_stdout:?}" + ); +} + #[test] fn no_args_prints_usage_and_exits_two() { let out = Command::new(BIN).output().expect("spawn aura");