extern crate alloc;
use alloc::collections::BTreeSet;
use super::super::{Record, Seq, arb_ops, run};
use crate::metis::Dot;
use proptest::prelude::*;
fn reachable_oracle(seq: &Seq, record: &Record) -> BTreeSet<Dot> {
let mut reachable = BTreeSet::new();
for &dot in record.woven.keys() {
if seq.store().locus(dot).is_none() {
continue;
}
let mut cursor = dot;
let mut seen = BTreeSet::new();
let reaches = loop {
let Some(locus) = seq.store().locus(cursor) else {
break false;
};
match locus.anchor.dot().map(Dot::try_from) {
None => break true,
Some(Err(_)) => break false,
Some(Ok(anchor)) => {
if !seen.insert(cursor) {
break false;
}
cursor = anchor;
}
}
};
if reaches {
let _ = reachable.insert(dot);
}
}
reachable
}
proptest! {
#[test]
fn prop_is_reachable_agrees_with_the_walk_oracle(ops in arb_ops()) {
let (live, record) = run(&ops);
for seq in &live {
let oracle = reachable_oracle(seq, &record);
for &dot in record.woven.keys() {
let held = seq.store().locus(dot).is_some();
let got = seq.store().is_reachable(dot);
prop_assert_eq!(got, held && oracle.contains(&dot));
}
}
}
}