extern crate alloc;
use alloc::vec;
use alloc::vec::Vec;
use core::num::NonZeroUsize;
use crate::kairos::Kairos;
use crate::metis::dot::RawDot;
use crate::metis::{
Adopted, Anchor, Cut, Declaration, Dot, DotSet, Dotted, EpochPreparation, EpochPreparationFold,
EpochPreparationMiss, EpochStratum, EpochStratumError, Epochs, Locus, Metatheses, Metathesis,
Rhapsody, Stability, Vouched,
};
#[track_caller]
fn d(station: u32, counter: u64) -> Dot {
Dot::from_parts(station, counter).expect("test literal names the non-dot counter zero")
}
type Text = Dotted<Rhapsody>;
type Moves = Dotted<Metatheses>;
fn rank(physical_ns: u64) -> Kairos {
Kairos::new(physical_ns, 0, 1, 0u16)
}
fn locus(anchor: Anchor, rank: Kairos) -> Locus {
Locus { anchor, rank }
}
fn text_delta(dot: Dot, locus: Locus) -> Text {
let mut text = Rhapsody::new();
assert!(text.weave(dot, locus));
Dotted::from_store(text)
}
fn move_delta(testimony: Dot, target: (u32, u64), anchor: Anchor, rank: Kairos) -> Moves {
Dotted::from_store(Metatheses::singleton(
testimony,
Metathesis {
target: target.into(),
to: locus(anchor, rank),
},
))
}
type LogEntries<S> = Vec<((u32, u64), S)>;
fn generation_log() -> (LogEntries<Text>, LogEntries<Moves>, Text, Moves) {
let text_entries = vec![
((1, 1), text_delta(d(1, 1), locus(Anchor::Origin, rank(3)))),
(
(1, 2),
text_delta(
d(1, 2),
locus(
Anchor::After(RawDot {
station: 1,
counter: 1,
}),
rank(5),
),
),
),
(
(2, 1),
text_delta(
d(2, 1),
locus(
Anchor::After(RawDot {
station: 1,
counter: 1,
}),
rank(4),
),
),
),
];
let move_entries = vec![((2, 2), move_delta(d(2, 2), (1, 2), Anchor::Origin, rank(9)))];
let mut text = Text::new();
for (_, delta) in &text_entries {
text.merge_from(delta);
}
let mut moves = Moves::new();
for (_, delta) in &move_entries {
moves.merge_from(delta);
}
(text_entries, move_entries, text, moves)
}
fn declared_and_adopted(text: &Text, moves: &Moves) -> (Declaration, Adopted) {
let coverage = text.context().merge(moves.context());
let boundary = Cut::floor_of(&coverage);
let dot = d(1, boundary.as_vector().get(1) + 1);
let mut stability = Stability::new([1, 2]);
stability.report_cut(1, &boundary).unwrap();
stability.report_cut(2, &boundary).unwrap();
let mut epochs = Epochs::new([1, 2], NonZeroUsize::new(1).unwrap());
let declaration = epochs
.declare(dot, rank(dot.counter()), &stability, &Cut::bottom())
.unwrap();
let mut delivered = boundary.as_vector().clone();
delivered.observe(dot.station(), dot.counter());
let delivered = Cut::from_witnessed(delivered);
stability.report_cut(1, &delivered).unwrap();
stability.report_cut(2, &delivered).unwrap();
epochs
.confirm(declaration.address(), &Vouched::trust(1, delivered.clone()))
.unwrap();
epochs
.confirm(declaration.address(), &Vouched::trust(2, delivered.clone()))
.unwrap();
let adopted = epochs
.adopt(1, delivered.as_vector().get(1), &stability)
.unwrap();
(declaration, adopted)
}
#[test]
fn the_declarer_dry_run_seeds_and_finishes_the_exact_stratum() {
let (_, _, text, moves) = generation_log();
let (declaration, adopted) = declared_and_adopted(&text, &moves);
let control = EpochStratum::new(&adopted, text.clone(), moves.clone()).unwrap();
let preparation = EpochPreparation::begin(&declaration, text, moves)
.expect("the dry-run pairs sit below their own declaration cut");
assert_eq!(preparation.address(), declaration.address());
assert_eq!(preparation.cut(), declaration.cut());
let staged = preparation
.finish(&adopted)
.expect("the staged winner is the adopted winner");
assert_eq!(staged.pristine(), control.pristine());
assert_eq!(
staged.into_transition().shadow.projection(),
control.into_transition().shadow.projection(),
);
}
#[test]
fn a_peer_stages_from_the_base_and_agrees_with_the_rebuild() {
let (text_entries, move_entries, text, moves) = generation_log();
let (declaration, adopted) = declared_and_adopted(&text, &moves);
let mut preparation = EpochPreparation::begin(&declaration, Text::new(), Moves::new())
.expect("the empty base sits below every cut");
for (dot, delta) in &text_entries {
assert_eq!(
preparation.absorb_text(&[(*dot).into()], delta),
EpochPreparationFold::Staged
);
}
for (dot, delta) in &move_entries {
assert_eq!(
preparation.absorb_moves(&[(*dot).into()], delta),
EpochPreparationFold::Staged
);
}
let staged = preparation
.finish(&adopted)
.expect("the covered log is exactly the fold input");
let control = EpochStratum::new(&adopted, text, moves).unwrap();
assert_eq!(staged.pristine(), control.pristine());
}
#[test]
fn a_window_delta_is_classified_and_left_unfolded() {
let (text_entries, move_entries, text, moves) = generation_log();
let (declaration, adopted) = declared_and_adopted(&text, &moves);
let mut preparation = EpochPreparation::begin(&declaration, Text::new(), Moves::new()).unwrap();
for (dot, delta) in &text_entries {
assert_eq!(
preparation.absorb_text(&[(*dot).into()], delta),
EpochPreparationFold::Staged
);
}
for (dot, delta) in &move_entries {
assert_eq!(
preparation.absorb_moves(&[(*dot).into()], delta),
EpochPreparationFold::Staged
);
}
assert_eq!(
preparation.absorb_text(
&[RawDot::new(2, 9)],
&text_delta(d(2, 9), locus(Anchor::Origin, rank(11)))
),
EpochPreparationFold::Window {
dot: RawDot::new(2, 9)
}
);
assert_eq!(
preparation.absorb_moves(
&[RawDot::new(2, 9)],
&move_delta(d(2, 9), (1, 1), Anchor::Origin, rank(12))
),
EpochPreparationFold::Window {
dot: RawDot::new(2, 9)
}
);
let staged = preparation.finish(&adopted).unwrap();
let control = EpochStratum::new(&adopted, text, moves).unwrap();
assert_eq!(staged.pristine(), control.pristine());
}
#[test]
fn a_recording_only_fragment_is_classified_by_its_skeleton() {
let (text_entries, move_entries, text, moves) = generation_log();
let (declaration, adopted) = declared_and_adopted(&text, &moves);
let mut preparation = EpochPreparation::begin(&declaration, Text::new(), Moves::new()).unwrap();
for (dot, delta) in &text_entries {
assert_eq!(
preparation.absorb_text(&[(*dot).into()], delta),
EpochPreparationFold::Staged
);
}
for (dot, delta) in &move_entries {
assert_eq!(
preparation.absorb_moves(&[(*dot).into()], delta),
EpochPreparationFold::Staged
);
}
let mut pair = Text::new();
pair.merge_from(&text_delta(d(2, 9), locus(Anchor::Origin, rank(11))));
let mut removal = DotSet::new();
assert!(removal.insert(d(2, 9)));
pair.merge_from(&Dotted::from_context(removal));
let fragment = Dotted::try_new(pair.store().clone(), DotSet::new())
.expect("an invisible skeleton needs no context coverage");
assert_eq!(
preparation.absorb_text(&[RawDot::new(1, 1)], &fragment),
EpochPreparationFold::Window {
dot: RawDot::new(2, 9)
}
);
let staged = preparation.finish(&adopted).unwrap();
let control = EpochStratum::new(&adopted, text, moves).unwrap();
assert_eq!(staged.pristine(), control.pristine());
assert_eq!(
EpochPreparation::begin(&declaration, fragment, Moves::new()).unwrap_err(),
EpochPreparationMiss::UnpinnedBase {
dot: RawDot::new(2, 9)
}
);
}
#[test]
fn a_post_cut_deletion_of_a_pre_cut_identity_is_window_traffic() {
let (text_entries, move_entries, text, moves) = generation_log();
let (declaration, adopted) = declared_and_adopted(&text, &moves);
let mut preparation = EpochPreparation::begin(&declaration, Text::new(), Moves::new()).unwrap();
for (dot, delta) in &text_entries {
assert_eq!(
preparation.absorb_text(&[(*dot).into()], delta),
EpochPreparationFold::Staged
);
}
for (dot, delta) in &move_entries {
assert_eq!(
preparation.absorb_moves(&[(*dot).into()], delta),
EpochPreparationFold::Staged
);
}
let mut deletion = DotSet::new();
assert!(deletion.insert(d(2, 9)));
assert!(deletion.insert(d(1, 1)));
assert_eq!(
preparation.absorb_text(
&[RawDot::new(2, 9)],
&Dotted::from_context(deletion.clone())
),
EpochPreparationFold::Window {
dot: RawDot::new(2, 9)
}
);
let mut move_retract = DotSet::new();
assert!(move_retract.insert(d(2, 10)));
assert!(move_retract.insert(d(2, 2)));
assert_eq!(
preparation.absorb_moves(&[RawDot::new(2, 10)], &Dotted::from_context(move_retract)),
EpochPreparationFold::Window {
dot: RawDot::new(2, 10)
}
);
let staged = preparation.finish(&adopted).unwrap();
let control = EpochStratum::new(&adopted, text, moves).unwrap();
assert_eq!(staged.pristine(), control.pristine());
assert!(
staged.pristine().woven().dots().next().is_some(),
"the retained at-cut content survives the misdirected deletion"
);
}
#[test]
fn an_undotted_retraction_is_unclassifiable_and_stays_window_side() {
let (text_entries, move_entries, text, moves) = generation_log();
let (declaration, adopted) = declared_and_adopted(&text, &moves);
let mut preparation = EpochPreparation::begin(&declaration, Text::new(), Moves::new()).unwrap();
for (dot, delta) in &text_entries {
assert_eq!(
preparation.absorb_text(&[(*dot).into()], delta),
EpochPreparationFold::Staged
);
}
for (dot, delta) in &move_entries {
assert_eq!(
preparation.absorb_moves(&[(*dot).into()], delta),
EpochPreparationFold::Staged
);
}
let mut retract = DotSet::new();
assert!(retract.insert(d(1, 1)));
let retraction = Dotted::from_context(retract);
assert_eq!(
preparation.absorb_text(&[], &retraction),
EpochPreparationFold::Window {
dot: RawDot::new(0, 0)
}
);
assert_eq!(
preparation.absorb_text(&[RawDot::new(2, 0)], &retraction),
EpochPreparationFold::Window {
dot: RawDot::new(2, 0)
}
);
let staged = preparation.finish(&adopted).unwrap();
let mut shadow = staged.into_transition().shadow;
let before = shadow.projection().order().len();
shadow
.deliver_text(&retraction)
.expect("a window retraction replays through the shadow");
let after = shadow.projection().order().len();
assert_eq!(
before - after,
1,
"the retracted identity leaves the judgment"
);
}
#[test]
fn an_unpinned_base_refuses_at_the_seam() {
let (_, _, text, moves) = generation_log();
let (declaration, _) = declared_and_adopted(&text, &moves);
let mut poisoned = text;
poisoned.merge_from(&text_delta(d(2, 9), locus(Anchor::Origin, rank(11))));
assert_eq!(
EpochPreparation::begin(&declaration, poisoned, moves).unwrap_err(),
EpochPreparationMiss::UnpinnedBase {
dot: RawDot::new(2, 9)
}
);
}
#[test]
fn a_losing_candidate_misses_with_both_addresses_named() {
let (_, _, text, moves) = generation_log();
let coverage = text.context().merge(moves.context());
let boundary = Cut::floor_of(&coverage);
let mut stability = Stability::new([1, 2]);
stability.report_cut(1, &boundary).unwrap();
stability.report_cut(2, &boundary).unwrap();
let dot_one = d(1, boundary.as_vector().get(1) + 1);
let dot_two = d(2, boundary.as_vector().get(2) + 1);
let mut epochs = Epochs::new([1, 2], NonZeroUsize::new(1).unwrap());
let losing = epochs
.declare(dot_one, rank(1), &stability, &Cut::bottom())
.unwrap();
let mut rival = Epochs::new([1, 2], NonZeroUsize::new(1).unwrap());
let winning = rival
.declare(dot_two, rank(9), &stability, &Cut::bottom())
.unwrap();
epochs.deliver(winning, &stability, &Cut::bottom()).unwrap();
let mut delivered = boundary.as_vector().clone();
delivered.observe(dot_one.station(), dot_one.counter());
delivered.observe(dot_two.station(), dot_two.counter());
let delivered = Cut::from_witnessed(delivered);
stability.report_cut(1, &delivered).unwrap();
stability.report_cut(2, &delivered).unwrap();
epochs
.confirm(losing.address(), &Vouched::trust(1, delivered.clone()))
.unwrap();
epochs
.confirm(losing.address(), &Vouched::trust(2, delivered.clone()))
.unwrap();
let adopted = epochs
.adopt(1, delivered.as_vector().get(1), &stability)
.unwrap();
assert_ne!(adopted.address(), losing.address());
let preparation = EpochPreparation::begin(&losing, text, moves).unwrap();
assert_eq!(
preparation.finish(&adopted).unwrap_err(),
EpochPreparationMiss::DifferentWinner {
staged: losing.address(),
adopted: adopted.address(),
}
);
}
#[test]
fn a_drifted_cut_names_the_first_disagreeing_station() {
let (_, _, text, moves) = generation_log();
let (_, adopted) = declared_and_adopted(&text, &moves);
let mut short = DotSet::new();
assert!(short.insert(d(1, 1)));
let short_boundary = Cut::floor_of(&short);
let mut stability = Stability::new([1, 2]);
stability.report_cut(1, &short_boundary).unwrap();
stability.report_cut(2, &short_boundary).unwrap();
let mut foreign = Epochs::new([1, 2], NonZeroUsize::new(1).unwrap());
let alien = foreign
.declare(adopted.dot(), adopted.rank(), &stability, &Cut::bottom())
.unwrap();
assert_eq!(alien.address(), adopted.address());
assert_ne!(alien.cut(), adopted.cut());
let preparation = EpochPreparation::begin(&alien, Text::new(), Moves::new()).unwrap();
let miss = preparation.finish(&adopted).unwrap_err();
assert!(matches!(
miss,
EpochPreparationMiss::DriftedCut { station: 1, .. }
));
}
#[test]
fn a_context_complete_but_content_empty_base_is_the_callers_log_obligation() {
let (_, _, text, moves) = generation_log();
let (declaration, adopted) = declared_and_adopted(&text, &moves);
let hollow = Dotted::from_context(declaration.cut().to_have_set());
let preparation = EpochPreparation::begin(&declaration, hollow, Moves::new()).unwrap();
let staged = preparation
.finish(&adopted)
.expect("a context-complete base passes the structural proof");
let control = EpochStratum::new(&adopted, text, moves).unwrap();
assert!(staged.pristine().woven().dots().next().is_none());
assert_ne!(staged.pristine(), control.pristine());
}
#[test]
fn an_unfed_staging_surfaces_the_stratum_refusal() {
let (_, _, text, moves) = generation_log();
let (declaration, adopted) = declared_and_adopted(&text, &moves);
let preparation = EpochPreparation::begin(&declaration, Text::new(), Moves::new()).unwrap();
assert!(matches!(
preparation.finish(&adopted).unwrap_err(),
EpochPreparationMiss::Stratum(EpochStratumError::Incomplete { .. })
));
}