extern crate alloc;
use alloc::collections::{BTreeMap, BTreeSet};
use alloc::vec::Vec;
use crate::kairos::{Clock, TickCounter};
use crate::metis::{Dot, DotSet, Dotted, Locus, Rhapsody};
use proptest::prelude::*;
use super::super::super::d;
use super::super::{REPLICAS, Record, Seq, arb_ops, reference_order, run};
fn reference_walk_sequence(woven: &BTreeMap<Dot, Locus>) -> Vec<Dot> {
reference_order(&Record {
woven: woven.clone(),
expelled: BTreeSet::new(),
})
}
pub(super) fn enrich_with_sided_edits(
live: &[Seq],
record: &mut Record,
edits: &[(usize, bool)],
) -> Seq {
let station = u32::try_from(REPLICAS + 1).unwrap();
let clk = Clock::with_default_config(TickCounter::new(), station).unwrap();
let mut seq = live.iter().fold(Seq::new(), |acc, r| acc.merge(r));
for &(caret_pick, delete_it) in edits {
let visible = seq.store().order();
let after = if visible.is_empty() {
None
} else {
Some(visible[caret_pick % visible.len()])
};
let anchor = seq.store().anchor_for_visual_insert(after.map(Into::into));
if let Some(top) = seq.store().children_of(anchor).next()
&& let Some(locus) = seq.store().locus(top)
{
clk.observe(locus.rank);
}
let dot = seq.next_dot(station);
let locus = Locus {
anchor,
rank: clk.now(0u16),
};
let mut rhapsody = Rhapsody::new();
assert!(rhapsody.weave(dot, locus));
seq = seq.merge(&Dotted::from_store(rhapsody));
let _ = record.woven.insert(dot, locus);
if delete_it {
let mut ctx = DotSet::new();
let _ = ctx.insert(dot);
seq = seq.merge(&Dotted::from_context(ctx));
let _ = record.expelled.insert(dot);
}
}
seq
}
proptest! {
#[test]
fn prop_order_walk_after_agrees_with_order_suffix(
ops in arb_ops(),
edits in prop::collection::vec((0usize..16, any::<bool>()), 0..6),
) {
let (live, mut record) = run(&ops);
let seq = enrich_with_sided_edits(&live, &mut record, &edits);
let store = seq.store();
let lazy: Vec<Dot> = store.order_walk().collect();
prop_assert_eq!(&lazy, &reference_order(&record));
let full = reference_walk_sequence(&record.woven);
let placed: BTreeSet<Dot> = full.iter().copied().collect();
for &dot in record.woven.keys() {
let walk = store.order_walk_after(dot);
prop_assert_eq!(
store.is_reachable(dot),
placed.contains(&dot),
"reachability and the oracle disagree at {:?}", dot
);
if placed.contains(&dot) {
let pos = full.iter().position(|&d| d == dot).unwrap();
let expected: Vec<Dot> = full[pos + 1..]
.iter()
.copied()
.filter(|&dot| store.is_visible(dot))
.collect();
let Some(iter) = walk else {
prop_assert!(false, "a placed element was refused: {:?}", dot);
unreachable!()
};
let got: Vec<Dot> = iter.collect();
prop_assert_eq!(got, expected, "suffix mismatch at {:?}", dot);
} else {
prop_assert!(walk.is_none(), "an unreachable dot resumed: {:?}", dot);
}
}
let fresh_station = u32::try_from(REPLICAS + 2).unwrap();
prop_assert!(store.order_walk_after(d(fresh_station, u64::MAX)).is_none());
prop_assert!(Dot::from_parts(fresh_station, 0).is_err());
let mut incremental = Seq::new();
incremental.merge_from(&seq);
for &dot in record.woven.keys() {
prop_assert_eq!(
incremental.store().is_reachable(dot),
store.is_reachable(dot),
"placement maintenance diverged from the rebuild at {:?}", dot
);
}
}
}