extern crate alloc;
use alloc::vec::Vec;
use core::num::NonZeroUsize;
use crate::metis::Anchor;
use crate::metis::tests::support::dot as d;
use super::super::fabric::Fabric;
use super::super::replica::Replica;
use super::super::{Note, act, assert_converged, fleet_of, resync};
use crate::metis::dot::RawDot;
#[test]
fn an_unfenced_mint_reused_after_restart_forks_identity() {
const ROSTER: [u32; 3] = [1, 2, 3];
let depth = NonZeroUsize::new(2).expect("positive");
let mut two = Replica::new(2, &ROSTER, depth);
let mut three = Replica::new(3, &ROSTER, depth);
let mut one = Replica::new(1, &ROSTER, depth);
let mut first_out = Vec::new();
let _ = one.insert_visible(0, &mut first_out);
let mut second_out = Vec::new();
let emitted = one.insert_visible(1, &mut second_out);
assert_eq!(emitted, d(1, 2), "the second mint");
for note in &first_out {
two.handle(note, &mut Vec::new());
three.handle(note, &mut Vec::new());
}
for note in &second_out {
two.handle(note, &mut Vec::new());
}
let mut journal = one.journal().clone();
journal
.notes
.retain(|note| !matches!(note, Note::Old { dots, .. } if dots.contains(&d(1, 2))));
let mut one = Replica::rehydrate(1, &ROSTER, depth, &journal);
let mut remint_out = Vec::new();
let reminted = one.insert_visible(0, &mut remint_out);
assert_eq!(
reminted,
d(1, 2),
"the forgotten allocator re-mints the emitted dot"
);
for note in &remint_out {
three.handle(note, &mut Vec::new());
}
let at_two = two
.text()
.store()
.locus(d(1, 2))
.expect("station 2 holds the original spelling")
.anchor;
let at_three = three
.text()
.store()
.locus(d(1, 2))
.expect("station 3 holds the re-minted spelling")
.anchor;
assert_eq!(
at_two,
Anchor::After(RawDot {
station: 1,
counter: 1
})
);
assert_eq!(
at_three,
Anchor::Before(RawDot {
station: 1,
counter: 1
})
);
for note in &second_out {
three.handle(note, &mut Vec::new());
}
for note in &remint_out {
two.handle(note, &mut Vec::new());
}
assert_eq!(
two.text()
.store()
.locus(d(1, 2))
.expect("still held")
.anchor,
Anchor::After(RawDot {
station: 1,
counter: 1
}),
"the survivor law keeps station 2's first spelling"
);
assert_eq!(
three
.text()
.store()
.locus(d(1, 2))
.expect("still held")
.anchor,
Anchor::Before(RawDot {
station: 1,
counter: 1
}),
"the survivor law keeps station 3's first spelling"
);
assert_ne!(
two.text().store().to_bytes(),
three.text().store().to_bytes(),
"one dot, two payloads: the fleet can never read one byte sequence again"
);
}
#[test]
fn an_unfenced_oath_lets_a_restarted_writer_strand_its_weave() {
const ROSTER: [u32; 3] = [1, 2, 3];
let depth = NonZeroUsize::new(2).expect("positive");
let mut fleet = fleet_of(&ROSTER, depth);
let mut fabric = Fabric::new(0x0A7B_0A7B, &ROSTER, 0);
let woven = act(&mut fabric, &mut fleet, 1, |replica, out| {
replica.insert_visible(0, out)
});
fabric.drain(&mut fleet);
let deleted = act(&mut fabric, &mut fleet, 3, |replica, out| {
replica.delete_visible(0, out)
});
assert_eq!(deleted, Some(woven), "station 3 deletes the element");
fabric.drain(&mut fleet);
for station in [1, 3] {
assert_eq!(
fleet.get_mut(&station).expect("roster member").condense(),
1,
"the gathered meet licenses the excision"
);
}
let mut journal = fleet[&2].journal().clone();
journal.notes.retain(
|note| !matches!(note, Note::Old { dots, .. } if dots.iter().any(|dot| dot.station() == 3)),
);
let _ = fleet.insert(2, Replica::rehydrate(2, &ROSTER, depth, &journal));
let stranded = act(&mut fabric, &mut fleet, 2, |replica, out| {
replica.insert_disciplined(1, out)
});
fabric.drain(&mut fleet);
assert!(
fleet[&2].text().store().is_reachable(stranded),
"the amnesiac reads its own weave in place"
);
for station in [1, 3] {
let replica = &fleet[&station];
let store = replica.text().store();
assert!(
store.locus(stranded).is_some(),
"the weave was delivered to station {station}"
);
assert!(
!store.is_reachable(stranded),
"the weave strands at excised station {station}: the forgotten \
oath re-anchored a dot the fleet had lawfully excised"
);
}
}
#[test]
fn a_report_beyond_the_fenced_floor_wedges_the_window_until_repair() {
const ROSTER: [u32; 3] = [1, 2, 3];
let depth = NonZeroUsize::new(2).expect("positive");
let mut fleet = fleet_of(&ROSTER, depth);
let mut fabric = Fabric::new(0x00D5_F100, &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 mut journal = fleet[&2].journal().clone();
journal
.notes
.retain(|note| !matches!(note, Note::Old { dots, .. } if dots.contains(&d(1, 2))));
let _ = fleet.insert(2, Replica::rehydrate(2, &ROSTER, depth, &journal));
let _ = act(&mut fabric, &mut fleet, 1, |replica, out| {
replica.try_declare(out)
})
.expect("the masked watermark licenses the declaration");
fabric.drain(&mut fleet);
for replica in fleet.values() {
assert_eq!(
replica.generation(),
1,
"no seal may fire while the window waits on the amnesiac"
);
assert!(
!replica.adopted(),
"no adoption without the amnesiac's confirmation"
);
}
resync(&mut fabric, &fleet, 2);
fabric.drain(&mut fleet);
for replica in fleet.values() {
assert_eq!(replica.generation(), 2, "the repaired window seals");
assert_eq!(replica.seals.len(), 1);
}
assert_converged(&fleet);
}