use std::time::{Duration, SystemTime};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub(crate) enum RecoverAction {
MarkDeadStopped,
ReattachVsockOnly,
}
#[must_use]
pub(crate) const fn recover_action(pid_alive: bool) -> RecoverAction {
if pid_alive {
RecoverAction::ReattachVsockOnly
} else {
RecoverAction::MarkDeadStopped
}
}
#[must_use]
pub(crate) fn idle_expired(
now: SystemTime,
last_activity: Option<SystemTime>,
created_at: SystemTime,
policy_secs: Option<u64>,
) -> bool {
let Some(secs) = policy_secs else {
return false;
};
if secs == 0 {
return false;
}
let anchor = last_activity.unwrap_or(created_at);
now.duration_since(anchor)
.unwrap_or(Duration::ZERO)
.as_secs()
>= secs
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[non_exhaustive]
pub struct SweepReport {
pub stopped: u32,
pub deleted: u32,
}
#[cfg(test)]
#[allow(clippy::unwrap_used, reason = "tests")]
mod tests {
use super::*;
#[test]
fn recover_dead() {
assert_eq!(recover_action(false), RecoverAction::MarkDeadStopped);
}
#[test]
fn recover_live_shim_including_secrets_is_vsock_only() {
assert_eq!(recover_action(true), RecoverAction::ReattachVsockOnly);
}
#[test]
fn idle_policy_default_off() {
let now = SystemTime::now();
assert!(!idle_expired(now, None, now, None));
assert!(!idle_expired(now, None, now, Some(0)));
}
#[test]
fn idle_expired_after_threshold() {
let created = epoch_plus(0);
let last = epoch_plus(10);
let now = epoch_plus(100);
assert!(idle_expired(now, Some(last), created, Some(50)));
assert!(!idle_expired(now, Some(last), created, Some(200)));
}
fn epoch_plus(secs: u64) -> SystemTime {
SystemTime::UNIX_EPOCH + Duration::from_secs(secs)
}
}