use super::*;
use wsb::output::Line;
fn started(seq: u64, id: u64, pid: u32, argv: &[&str]) -> crate::web::ops::OutputLine {
crate::web::op_log::output_line_of(Line {
seq,
ts: "2026-08-24T10:00:00.000Z".to_string(),
record: Record::SubprocessStarted {
id,
argv: argv.iter().map(|a| a.to_string()).collect(),
cwd: Some("/w".to_string()),
pid,
},
})
}
fn finished(seq: u64, id: u64) -> crate::web::ops::OutputLine {
crate::web::op_log::output_line_of(Line {
seq,
ts: "2026-08-24T10:00:01.000Z".to_string(),
record: Record::SubprocessFinished {
id,
exit_code: Some(0),
signal: None,
duration_ms: 1000,
},
})
}
fn fold(lines: &[crate::web::ops::OutputLine]) -> Vec<RunningChild> {
let mut running: BTreeMap<u64, RunningChild> = BTreeMap::new();
for line in lines {
match &line.record {
Record::SubprocessStarted { id, argv, cwd, pid } => {
running.insert(
*id,
RunningChild {
id: *id,
pid: *pid,
argv: argv.clone(),
cwd: cwd.clone(),
started_at: line.ts.clone(),
},
);
}
Record::SubprocessFinished { id, .. } => {
running.remove(id);
}
_ => {}
}
}
running.into_values().collect()
}
#[test]
fn test11092_a_finished_child_is_not_running() {
let lines = vec![
started(1, 1, 100, &["bash", "-c", "cargo build"]),
started(2, 2, 200, &["bash", "-c", "go test ./..."]),
finished(3, 1),
];
let running = fold(&lines);
assert_eq!(running.len(), 1);
assert_eq!(running[0].pid, 200);
}
#[test]
fn test11093_a_child_carries_what_identifies_it() {
let lines = vec![started(1, 1, 4242, &["bash", "-c", "cargo test --features x"])];
let running = fold(&lines);
assert_eq!(running[0].pid, 4242);
assert_eq!(running[0].argv.len(), 3);
assert_eq!(running[0].started_at.as_deref(), Some("2026-08-24T10:00:00.000Z"));
}
#[test]
fn test11094_a_pid_this_operation_never_started_is_refused() {
let known: Vec<u32> = fold(&[started(1, 1, 100, &["bash"])])
.iter()
.map(|c| c.pid)
.collect();
assert!(known.contains(&100));
assert!(!known.contains(&1), "init is not one of this run's children");
assert!(!known.contains(&99999));
}