use super::super::{OpEntry, Origin};
use super::*;
fn row(argv: &str, cwd: &str, exit: i32) -> OpRow {
OpRow::from(&OpEntry {
ts: "TS".into(),
argv: argv.split(' ').map(String::from).collect(),
cwd: cwd.into(),
exit,
stdout: String::new(),
stderr: if exit == 0 {
String::new()
} else {
"boom".into()
},
origin: Origin::default(),
client: crate::registry::Client::default(),
})
}
use OpOutcome::{Clean, Detached, Failed, Retired};
const NOTICE_LINE: &str = "litany: exit launch for c-1: no such file \
(accepted crash class, ARCH §2.11)\n";
fn detached(argv: &str, cwd: &str, stderr: &str) -> OpRow {
OpRow::from(&OpEntry {
ts: "TS".into(),
argv: argv.split(' ').map(String::from).collect(),
cwd: cwd.into(),
exit: super::super::DETACHED_EXIT,
stdout: String::new(),
stderr: stderr.into(),
origin: Origin::default(),
client: crate::registry::Client::default(),
})
}
fn handoff(argv: &str, cwd: &str) -> OpRow {
detached(argv, cwd, "")
}
#[test]
fn a_later_clean_run_of_the_same_verb_retires_the_failure() {
let rows = [row("litany prime", "/w", 2), row("litany prime", "/w", 0)];
assert_eq!(outcomes(&rows), vec![Retired, Clean]);
assert_eq!(activity(&rows).errors, 0, "the chip counts no live failure");
}
#[test]
fn a_failure_with_no_later_clean_run_stays_live() {
let rows = [row("litany prime", "/w", 0), row("litany prime", "/w", 2)];
assert_eq!(outcomes(&rows), vec![Clean, Failed]);
assert_eq!(activity(&rows).errors, 1);
}
#[test]
fn retirement_is_scoped_to_the_cwd_it_ran_in() {
let rows = [row("litany prime", "/a", 2), row("litany prime", "/b", 0)];
assert_eq!(
outcomes(&rows),
vec![Failed, Clean],
"a clean run elsewhere leaves this project's failure live"
);
}
#[test]
fn the_verb_key_is_binary_plus_subcommand_not_the_operands() {
let same = [row("bl close bl-1", "/p", 1), row("bl close bl-2", "/p", 0)];
assert_eq!(outcomes(&same), vec![Retired, Clean]);
let other = [
row("bl close bl-1", "/p", 1),
row("bl list --json", "/p", 0),
];
assert_eq!(outcomes(&other), vec![Failed, Clean]);
let bare = [row("bz", "/p", 1), row("bz", "/p", 0)];
assert_eq!(outcomes(&bare), vec![Retired, Clean]);
}
#[test]
fn only_live_failures_reach_the_chip() {
let rows = [
row("litany prime", "/w", 2), row("bl close bl-1", "/p", 1),
row("litany prime", "/w", 0),
];
let a = activity(&rows);
assert_eq!(
a,
Activity {
total: 3,
errors: 1,
drifts: 0
}
);
assert_eq!(a.chip(), "activity · 3 ops · 1 failed ⚠");
assert!(a.chip().contains(crate::badge::op_badge(Failed).1));
assert_eq!(activity(&rows[2..]).chip(), "activity · 1 ops");
assert_eq!(activity(&[]).chip(), "activity · 0 ops");
assert!(outcomes(&[]).is_empty());
}
#[test]
fn a_clean_handoff_is_its_own_outcome_not_clean_and_not_failed() {
let rows = [handoff("litany prompt", "/ws")];
assert_eq!(outcomes(&rows), vec![Detached]);
}
#[test]
fn a_handoff_does_not_move_the_chip_failed_count() {
let rows = [handoff("litany prompt", "/ws")];
let a = activity(&rows);
assert_eq!(
a,
Activity {
total: 1,
errors: 0,
drifts: 0
}
);
assert_eq!(a.chip(), "activity · 1 ops");
}
#[test]
fn a_handoff_retires_an_earlier_failure_of_the_same_verb() {
let rows = [
row("litany prompt", "/ws", 2),
handoff("litany prompt", "/ws"),
];
assert_eq!(outcomes(&rows), vec![Retired, Detached]);
assert_eq!(activity(&rows).errors, 0, "the retired failure is not live");
}
#[test]
fn a_post_launch_death_reads_failed_not_detached() {
let died = detached("litany prompt", "/ws", "refusing: version skew\n");
assert_eq!(outcomes(&[died]), vec![Failed]);
}
#[test]
fn a_driver_that_carried_on_is_an_ordinary_handoff() {
let a = activity(&[handoff("litany prompt", "/ws")]);
assert_eq!(a.errors, 0);
assert!(!a.alarming(), "and the pane offers no Dismiss for it");
}
#[test]
fn a_folded_sink_stays_a_failure_whatever_it_says() {
let mixed = detached(
"litany prompt",
"/ws",
&format!("{NOTICE_LINE}litany: brazen 0.0.2 != 0.0.3\n"),
);
assert_eq!(outcomes(std::slice::from_ref(&mixed)), vec![Failed]);
assert_eq!(activity(&[mixed]).errors, 1);
let benign = detached("litany prompt", "/ws", NOTICE_LINE);
assert_eq!(outcomes(std::slice::from_ref(&benign)), vec![Failed]);
assert_eq!(activity(&[benign]).errors, 1);
}