extern crate alloc;
use alloc::vec;
use alloc::vec::Vec;
use core::num::NonZeroUsize;
use crate::metis::tests::support::dot as d;
use super::super::fabric::Fabric;
use super::super::replica::Replica;
use super::super::{Note, act, fleet_of};
#[test]
fn a_retirement_acknowledgement_counts_only_when_its_cut_is_delivered() {
const ROSTER: [u32; 3] = [1, 2, 3];
let depth = NonZeroUsize::new(2).expect("positive");
let mut one = Replica::new(1, &ROSTER, depth);
let mut two = Replica::new(2, &ROSTER, depth);
let mut three = Replica::new(3, &ROSTER, depth);
let mut outbox_one = Vec::new();
let _ = one.insert_visible(0, &mut outbox_one);
let mut round = outbox_one;
while !round.is_empty() {
let mut next = Vec::new();
for note in &round {
for replica in [&mut one, &mut two, &mut three] {
let mut out = Vec::new();
replica.handle(note, &mut out);
next.extend(out);
}
}
round = next;
}
let mut outbox_two = Vec::new();
let _ = two.insert_visible(1, &mut outbox_two);
let weave_x = outbox_two
.iter()
.find(|note| matches!(note, Note::Old { .. }))
.cloned()
.expect("the weave note");
let mut relay = Vec::new();
one.handle(&weave_x, &mut relay);
let mut outbox_delete = Vec::new();
let deleted = two.delete_visible(0, &mut outbox_delete);
assert_eq!(deleted, Some(d(1, 1)), "station 2 deletes T");
let mut round: Vec<Note> = Vec::new();
round.extend(
outbox_two
.iter()
.filter(|note| !matches!(note, Note::Old { .. }))
.cloned(),
);
round.extend(relay);
round.extend(outbox_delete);
while !round.is_empty() {
let mut next = Vec::new();
for note in &round {
for replica in [&mut one, &mut two, &mut three] {
let mut out = Vec::new();
replica.handle(note, &mut out);
next.extend(out);
}
}
round = next;
}
assert_eq!(
three.condense(),
0,
"parked acknowledgements withhold the witness"
);
assert_eq!(one.condense(), 0, "a fertile tombstone never excises");
let mut flood = vec![weave_x];
while let Some(note) = flood.pop() {
for replica in [&mut one, &mut two, &mut three] {
let mut out = Vec::new();
replica.handle(¬e, &mut out);
flood.extend(out);
}
}
assert_eq!(one.effective_order(), two.effective_order());
assert_eq!(one.effective_order(), three.effective_order());
assert_eq!(one.effective_order().len(), 1, "X alone is visible");
assert_eq!(
three.condense(),
0,
"a complete witness still never excises a fertile tombstone"
);
let mut outbox_delete_x = Vec::new();
let deleted = two.delete_visible(0, &mut outbox_delete_x);
assert_eq!(deleted, Some(d(2, 1)), "station 2 deletes X");
let mut flood = outbox_delete_x;
while let Some(note) = flood.pop() {
for replica in [&mut one, &mut two, &mut three] {
let mut out = Vec::new();
replica.handle(¬e, &mut out);
flood.extend(out);
}
}
for replica in [&mut one, &mut two, &mut three] {
assert_eq!(replica.condense(), 2, "X tip-first, then T");
}
assert_eq!(one.text().store().to_bytes(), two.text().store().to_bytes());
assert_eq!(
one.text().store().to_bytes(),
three.text().store().to_bytes()
);
}
#[test]
fn retirement_evidence_is_generation_scoped() {
const ROSTER: [u32; 3] = [1, 2, 3];
let mut fleet = fleet_of(&ROSTER, NonZeroUsize::new(2).expect("positive"));
let mut fabric = Fabric::new(0xF1EE_7005, &ROSTER, 0);
let _ = act(&mut fabric, &mut fleet, 1, |replica, out| {
replica.insert_visible(0, out)
});
let _ = act(&mut fabric, &mut fleet, 1, |replica, out| {
replica.insert_visible(1, out)
});
fabric.drain(&mut fleet);
let deleted = act(&mut fabric, &mut fleet, 1, |replica, out| {
replica.delete_visible(1, out)
});
assert_eq!(deleted, Some(d(1, 2)));
fabric.drain(&mut fleet);
let _ = act(&mut fabric, &mut fleet, 2, |replica, out| {
replica.try_declare(out)
})
.expect("the settled watermark licenses the declaration");
fabric.drain(&mut fleet);
for replica in fleet.values() {
assert_eq!(replica.generation(), 2);
}
let minted = act(&mut fabric, &mut fleet, 1, |replica, out| {
replica.insert_visible(1, out)
});
assert_eq!(minted, d(1, 2), "the compacted plane recurs the numeral");
fabric.drain(&mut fleet);
let replica = fleet.get_mut(&1).expect("roster member");
let mut outbox = Vec::new();
let deleted = replica.delete_visible(1, &mut outbox);
assert_eq!(deleted, Some(d(1, 2)));
let delete_note = outbox
.iter()
.find(|note| matches!(note, Note::Old { .. }))
.cloned()
.expect("the delete note");
let mut sink = Vec::new();
fleet
.get_mut(&3)
.expect("roster member")
.handle(&delete_note, &mut sink);
assert_eq!(
fleet.get_mut(&3).expect("roster member").condense(),
0,
"a fresh generation's meet starts empty"
);
}
#[test]
fn an_outrun_testimony_is_not_an_orphan() {
const ROSTER: [u32; 3] = [1, 2, 3];
let depth = NonZeroUsize::new(2).expect("positive");
let mut one = Replica::new(1, &ROSTER, depth);
let mut two = Replica::new(2, &ROSTER, depth);
let mut three = Replica::new(3, &ROSTER, depth);
let mut round = Vec::new();
let _ = one.insert_visible(0, &mut round);
while !round.is_empty() {
let mut next = Vec::new();
for note in &round {
for replica in [&mut one, &mut two, &mut three] {
let mut out = Vec::new();
replica.handle(note, &mut out);
next.extend(out);
}
}
round = next;
}
let mut outbox = Vec::new();
let woven = one.insert_visible(1, &mut outbox);
assert_eq!(woven, d(1, 2), "B is station 1's second weave");
let weave_b = outbox
.iter()
.find(|note| matches!(note, Note::Old { .. }))
.cloned()
.expect("the weave note");
let mut outbox_move = Vec::new();
let moved = one.move_visible(1, None, &mut outbox_move);
assert_eq!(moved, Some(d(1, 3)), "the testimony dot");
let move_note = outbox_move
.iter()
.find(|note| matches!(note, Note::Old { .. }))
.cloned()
.expect("the move note");
let mut sink = Vec::new();
three.handle(&move_note, &mut sink);
assert_eq!(
three.retire_orphans(&mut Vec::new()),
None,
"a missing locus without removal evidence is an outrun, not an orphan"
);
let mut flood = vec![weave_b, move_note];
flood.extend(sink);
while let Some(note) = flood.pop() {
for replica in [&mut one, &mut two, &mut three] {
let mut out = Vec::new();
replica.handle(¬e, &mut out);
flood.extend(out);
}
}
assert_eq!(one.effective_order(), three.effective_order());
assert_eq!(two.effective_order(), three.effective_order());
assert_eq!(
three.effective_order().first(),
Some(&d(1, 2)),
"the outrun move survived the hygiene pass and resolved"
);
}