use ohno::AppError;
use crate::OutputFailedError;
use crate::gc::live_sessions;
use crate::list_fmt::format_list;
use crate::output::print_line;
use crate::pal::processes::Processes;
use crate::pal::session_store::SessionStore;
use crate::trace::{Trace, trace};
pub(crate) fn execute(
store: &impl SessionStore,
processes: &impl Processes,
now_unix_ms: u64,
trace: Trace,
) -> Result<(), AppError> {
let live = live_sessions(store, processes, trace)?;
trace!(
trace,
"ages are measured against unix time {now_unix_ms} ms"
);
print_line(format_args!("{}", format_list(&live, now_unix_ms)))
.map_err(OutputFailedError::caused_by)?;
Ok(())
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use std::path::Path;
use tempfile::TempDir;
use super::*;
use crate::AppCommand;
use crate::pal::processes::{MockProcesses, ProcessLiveness};
use crate::pal::session_store::{FsSessionStore, SessionStore};
use crate::protocol::PROTOCOL_VERSION;
use crate::session_record::{ProcessIdentity, SessionRecord};
const SOME_NOW_MS: u64 = 60_000;
fn publish_session(store: &FsSessionStore, dir: &Path) {
let id = store.allocate_id(&ProcessIdentity::for_test(1)).unwrap();
store
.publish(&SessionRecord {
id,
supervisor: ProcessIdentity {
pid: 10,
creation_time: 100,
},
pipe_name: "pipe".to_string(),
launch_directory: dir.to_path_buf(),
command: AppCommand::for_test(&["app.exe"]),
started_at_unix_ms: 1,
attached: false,
protocol_version: PROTOCOL_VERSION,
})
.unwrap();
}
#[test]
#[cfg_attr(miri, ignore)]
fn empty_store_succeeds() {
let dir = TempDir::new().unwrap();
let store = FsSessionStore::new(dir.path().to_path_buf());
let processes = MockProcesses::new();
execute(&store, &processes, SOME_NOW_MS, Trace::default()).unwrap();
}
#[test]
#[cfg_attr(miri, ignore)]
fn live_session_is_kept() {
let dir = TempDir::new().unwrap();
let store = FsSessionStore::new(dir.path().to_path_buf());
publish_session(&store, dir.path());
let mut processes = MockProcesses::new();
processes
.expect_probe()
.returning(|_| ProcessLiveness::Live);
execute(&store, &processes, SOME_NOW_MS, Trace::default()).unwrap();
assert_eq!(store.list().unwrap().len(), 1);
}
#[test]
#[cfg_attr(miri, ignore)]
fn dead_session_is_reaped() {
let dir = TempDir::new().unwrap();
let store = FsSessionStore::new(dir.path().to_path_buf());
publish_session(&store, dir.path());
let mut processes = MockProcesses::new();
processes
.expect_probe()
.returning(|_| ProcessLiveness::Dead);
execute(&store, &processes, SOME_NOW_MS, Trace::default()).unwrap();
assert!(store.list().unwrap().is_empty());
}
}