use fsqlite_types::Region;
use crate::region::RegionState;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ChildRegionQuiescence {
pub region: Region,
pub state: Option<RegionState>,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RegionQuiescenceSnapshot {
pub region: Region,
pub state: RegionState,
pub active_tasks: usize,
pub active_obligations: usize,
pub non_closed_children: Vec<ChildRegionQuiescence>,
}
impl RegionQuiescenceSnapshot {
#[must_use]
pub fn is_quiescent(&self) -> bool {
self.active_tasks == 0
&& self.active_obligations == 0
&& self.non_closed_children.is_empty()
}
#[must_use]
pub fn blocker_count(&self) -> usize {
usize::from(self.active_tasks > 0)
+ usize::from(self.active_obligations > 0)
+ usize::from(!self.non_closed_children.is_empty())
}
}
#[cfg(test)]
mod tests {
use super::{ChildRegionQuiescence, RegionQuiescenceSnapshot};
use crate::region::RegionState;
use fsqlite_types::Region;
#[test]
fn region_quiescence_snapshot_detects_blockers() {
let snapshot = RegionQuiescenceSnapshot {
region: Region::new(7),
state: RegionState::Closing,
active_tasks: 2,
active_obligations: 1,
non_closed_children: vec![ChildRegionQuiescence {
region: Region::new(9),
state: Some(RegionState::Closing),
}],
};
assert!(!snapshot.is_quiescent());
assert_eq!(snapshot.blocker_count(), 3);
}
#[test]
fn region_quiescence_snapshot_accepts_closed_leaf() {
let snapshot = RegionQuiescenceSnapshot {
region: Region::new(3),
state: RegionState::Closing,
active_tasks: 0,
active_obligations: 0,
non_closed_children: Vec::new(),
};
assert!(snapshot.is_quiescent());
assert_eq!(snapshot.blocker_count(), 0);
}
}