use super::{banner, model, world};
use crate::git_tree::tests::fixture::Fixture;
use crate::opslog::{self, DETACHED_EXIT, Origin};
use std::fs;
use std::path::{Path, PathBuf};
use std::time::Duration;
fn derivable(w: &super::super::World) -> (Fixture, PathBuf) {
let fx = Fixture::new();
let ws = w.roots.yog_data.join("workspaces").join("gecko");
std::os::unix::fs::symlink(&fx.path, &ws).unwrap();
(fx, ws)
}
const MINTED: &str = "vanished-heron";
const CRY: &str = "brazen 0.0.2 refuses 0.0.3\n";
fn launch(m: &crate::AppModel, ts: &str, ws: &Path) {
opslog::append(
m.state_root(),
&opslog::OpEntry {
ts: ts.into(),
argv: vec![
"litany".into(),
"prompt".into(),
"--name".into(),
MINTED.into(),
ws.to_string_lossy().into_owned(),
"goal".into(),
],
cwd: ws.to_string_lossy().into_owned(),
exit: DETACHED_EXIT,
stdout: String::new(),
stderr: String::new(),
origin: Origin::Conversation,
},
)
.unwrap();
}
fn cry(m: &crate::AppModel, ts: &str, ws: &Path) {
let sink = opslog::detached::sink(m.state_root(), ts, ws);
fs::create_dir_all(sink.parent().unwrap()).unwrap();
fs::write(&sink, CRY).unwrap();
}
#[test]
fn a_detached_prompt_that_died_after_launch_surfaces_on_the_next_sweep() {
let w = world();
let (_fx, ws) = derivable(&w);
let (clock, mut m) = model(&w);
launch(&m, "0", &ws);
clock.advance(Duration::from_mins(10));
m.after_litany_verb();
m.tick(); assert!(banner(&m, Origin::Conversation).is_none());
assert!(!m.snap.ops.last().unwrap().failed());
assert!(!m.snap.ops.last().unwrap().has_output());
cry(&m, "0", &ws);
m.after_litany_verb();
m.tick(); let row = m.snap.ops.last().unwrap();
assert!(row.failed(), "a launch that produced nothing is a failure");
assert!(row.has_output(), "and the pane offers the expansion");
assert_eq!(
crate::opslog::rows::stderr_tail(&banner(&m, Origin::Conversation).unwrap().stderr),
CRY.trim_end()
);
assert!(
banner(&m, Origin::Balls).is_none(),
"the balls fold offered no bare rung and says nothing"
);
assert_eq!(
opslog::tail(m.state_root(), 8).len(),
1,
"no line rewritten"
);
}
#[test]
fn a_launch_inside_the_grace_window_never_alarms_however_its_sink_reads() {
let w = world();
let (_fx, ws) = derivable(&w);
let (_c, mut m) = model(&w);
launch(&m, "0", &ws);
cry(&m, "0", &ws);
m.after_litany_verb();
m.tick(); let row = m.snap.ops.last().unwrap();
assert!(
!row.failed(),
"a launch still inside its grace is no failure"
);
assert!(row.stderr.is_empty(), "and its sink was never read");
assert!(!row.has_output());
assert!(
banner(&m, Origin::Conversation).is_none(),
"the surface that fired it is not bannered"
);
assert_eq!(m.activity().errors, 0, "and the chip counts no failure");
}