extern crate alloc;
mod classification;
mod durability;
mod retirement;
mod writer;
use alloc::vec;
use alloc::vec::Vec;
use core::num::NonZeroUsize;
use crate::metis::tests::support::dot as d;
use crate::metis::{Cut, DotSet};
use super::Note;
use super::replica::Replica;
#[test]
fn out_of_reach_protocol_notes_park_once_and_cure_on_the_prerequisite() {
const ROSTER: [u32; 3] = [1, 2, 3];
let depth = NonZeroUsize::new(2).expect("positive");
let mut two = Replica::new(2, &ROSTER, depth);
let future = Note::Report {
generation: 2,
station: 3,
cut: Cut::floor_of(&DotSet::new()),
};
let mut applied = DotSet::new();
let _ = applied.insert(d(1, 1));
let blocked = Note::Retire {
generation: 1,
station: 3,
applied: applied.clone(),
at: Cut::floor_of(&applied),
};
for _ in 0..5 {
two.handle(&future, &mut Vec::new());
two.handle(&blocked, &mut Vec::new());
}
assert_eq!(two.parked_len(), 2, "an exact duplicate re-parks nothing");
assert_eq!(
two.volatile_len() + two.journal_notes_len(),
2,
"each distinct out-of-reach note is recorded exactly once, fenced \
or pending, however many repair rounds re-stated it"
);
let mut one = Replica::new(1, &ROSTER, depth);
let mut outbox = Vec::new();
let _ = one.insert_visible(0, &mut outbox);
for note in &outbox {
two.handle(note, &mut Vec::new());
}
assert_eq!(
two.parked_len(),
1,
"the cut-gated oath retried and counted; the future report waits"
);
}
#[test]
fn a_sealed_peer_restates_a_zero_counter_adoption_report() {
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 seed = Vec::new();
let _ = one.insert_visible(0, &mut seed);
let mut out_two = Vec::new();
let _ = two.insert_visible(1, &mut out_two);
seed.extend(out_two);
let mut flood = seed;
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);
}
}
let mut flood = Vec::new();
let _ = one
.try_declare(&mut flood)
.expect("a settled watermark self-supports the declaration");
while let Some(note) = flood.pop() {
for replica in [&mut one, &mut two, &mut three] {
if replica.id() == 1 && matches!(note, Note::Adoption { station: 3, .. }) {
continue;
}
let mut out = Vec::new();
replica.handle(¬e, &mut out);
flood.extend(out);
}
}
assert_eq!(two.generation(), 2, "station 2 seals");
assert_eq!(three.generation(), 2, "station 3 seals");
assert_eq!(one.generation(), 1, "the laggard waits on the lost report");
assert!(one.adopted(), "the laggard adopted before the loss");
let journal = one.journal().clone();
let mut one = Replica::rehydrate(1, &ROSTER, depth, &journal);
let mut flood = Vec::new();
for peer in [&two, &three] {
peer.reserve_logs(&mut flood);
peer.restate(&mut flood);
}
while let Some(note) = flood.pop() {
let mut out = Vec::new();
one.handle(¬e, &mut out);
for response in out {
let mut echo = Vec::new();
two.handle(&response, &mut echo);
three.handle(&response, &mut echo);
flood.extend(echo);
}
}
assert_eq!(
one.generation(),
2,
"the restated zero-counter adoption report completes the seal"
);
assert_eq!(one.seals, two.seals, "the seal record agrees");
assert_eq!(one.effective_order(), two.effective_order());
}
#[test]
fn no_seal_outruns_a_member_missing_window_traffic() {
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 flood = Vec::new();
let mut out = Vec::new();
let _ = one.insert_visible(0, &mut out);
flood.extend(out);
let mut out = Vec::new();
let _ = two.insert_visible(1, &mut out);
flood.extend(out);
let mut out = Vec::new();
let _ = three.insert_visible(2, &mut out);
flood.extend(out);
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);
}
}
let mut declare_out = Vec::new();
let _ = one
.try_declare(&mut declare_out)
.expect("a settled watermark self-supports the declaration");
let mut two_out = Vec::new();
for note in &declare_out {
two.handle(note, &mut two_out);
}
let mut mint_out = Vec::new();
let _ = two.insert_visible(0, &mut mint_out);
let window_delta = mint_out
.iter()
.find(|note| matches!(note, Note::Old { .. }))
.cloned()
.expect("the window mint");
let mut flood = Vec::new();
flood.extend(declare_out);
flood.extend(two_out);
flood.extend(mint_out);
while let Some(note) = flood.pop() {
for replica in [&mut one, &mut two, &mut three] {
if replica.id() == 3 && note == window_delta {
continue;
}
let mut out = Vec::new();
replica.handle(¬e, &mut out);
flood.extend(out);
}
}
for replica in [&one, &two, &three] {
assert_eq!(
replica.generation(),
1,
"replica {}: no seal while a member misses window traffic",
replica.id()
);
assert_eq!(replica.epochs().sealed().count(), 0);
}
let mut flood = vec![window_delta];
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 [&one, &two, &three] {
assert_eq!(replica.generation(), 2, "the delivered delta unblocks");
}
assert_eq!(one.effective_order(), two.effective_order());
assert_eq!(two.effective_order(), three.effective_order());
}