extern crate alloc;
mod model;
mod shipped;
use alloc::vec::Vec;
use core::array;
use core::cmp::Ordering;
use core::num::NonZeroUsize;
use proptest::prelude::*;
use crate::kairos::Kairos;
use crate::metis::dot::RawDot;
use crate::metis::{
Anchor, Cut, Dot, DotSet, Dotted, EpochPreparation, EpochPreparationMiss, Epochs, Locus,
Metatheses, Metathesis, Rhapsody, Stability, VersionVector,
};
#[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 vector(entries: &[(u32, u64)]) -> VersionVector {
let mut vector = VersionVector::new();
for &(station, count) in entries {
vector.observe(station, count);
}
vector
}
fn text_delta(dot: Dot, anchor: Anchor, at: Kairos) -> Text {
let mut text = Rhapsody::new();
assert!(text.weave(dot, Locus { anchor, rank: at }));
Dotted::from_store(text)
}
fn move_delta(testimony: Dot, target: (u32, u64), at: Kairos) -> Moves {
Dotted::from_store(Metatheses::singleton(
testimony,
Metathesis {
target: target.into(),
to: Locus {
anchor: Anchor::Origin,
rank: at,
},
},
))
}
#[test]
fn the_full_roster_meet_is_the_largest_chooser_agnostic_eager_bound() {
let oath_one = vector(&[(1, 4), (2, 4)]);
let oath_two = vector(&[(1, 1), (2, 1)]);
let full_meet = oath_one.meet(&oath_two);
assert_eq!(full_meet, oath_two);
let mut stability = Stability::new([1, 2]);
let declared = Cut::from_witnessed(vector(&[(1, 2), (2, 2)]));
stability.report_cut(1, &declared).unwrap();
stability.report_cut(2, &declared).unwrap();
let mut epochs = Epochs::new([1, 2], NonZeroUsize::new(1).unwrap());
let declaration = epochs
.declare(d(2, 3), rank(3), &stability, &Cut::bottom())
.unwrap();
assert!(&oath_two <= declaration.cut().as_vector());
assert!(declaration.cut().as_vector().happens_before(&oath_one));
let trailing = Text::from_context(Cut::from_witnessed(oath_one).to_have_set());
assert_eq!(
EpochPreparation::begin(&declaration, trailing, Moves::new()).unwrap_err(),
EpochPreparationMiss::UnpinnedBase {
dot: RawDot::new(1, 4)
}
);
let trailing = Text::from_context(Cut::from_witnessed(full_meet).to_have_set());
assert!(EpochPreparation::begin(&declaration, trailing, Moves::new()).is_ok());
}
fn arb_oath() -> impl Strategy<Value = VersionVector> {
prop::collection::btree_map(1u32..=3, 1u64..=6, 0..=3).prop_map(|counts| {
let mut oath = VersionVector::new();
for (station, count) in counts {
oath.observe(station, count);
}
oath
})
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(256))]
#[test]
fn prop_any_bound_strictly_above_the_roster_meet_is_undershot(
oaths in prop::collection::vec(arb_oath(), 2..=4),
bump_station in 1u32..=3,
bump in 1u64..=4,
) {
let meet = oaths
.iter()
.skip(1)
.fold(oaths[0].clone(), |folded, oath| folded.meet(oath));
let mut bound = meet.clone();
bound.observe(bump_station, meet.get(bump_station) + bump);
let excluded = oaths.iter().position(|oath| {
!matches!(
bound.partial_cmp(oath),
Some(Ordering::Less | Ordering::Equal)
)
});
let Some(member) = excluded else {
return Err(TestCaseError::fail(
"a bound strictly above the meet must exceed some member's oath",
));
};
let station = u32::try_from(member + 1).expect("small rosters");
let cut = Cut::from_witnessed(oaths[member].clone());
let mut stability = Stability::new([1, 2, 3, 4]);
for reporter in [1, 2, 3, 4] {
stability.report_cut(reporter, &cut).unwrap();
}
let fresh = oaths[member].get(station) + 1;
let mut epochs = Epochs::new([1, 2, 3, 4], NonZeroUsize::new(1).unwrap());
let declaration = epochs
.declare(d(station, fresh), rank(1), &stability, &Cut::bottom())
.unwrap();
prop_assert_eq!(declaration.cut().as_vector(), &oaths[member]);
let trailing = Text::from_context(Cut::from_witnessed(bound).to_have_set());
let refused = EpochPreparation::begin(&declaration, trailing, Moves::new());
let refused = matches!(refused, Err(EpochPreparationMiss::UnpinnedBase { .. }));
prop_assert!(refused, "the bound-advanced base is refused at the seam");
let trailing = Text::from_context(Cut::from_witnessed(meet).to_have_set());
let served = EpochPreparation::begin(&declaration, trailing, Moves::new());
prop_assert!(served.is_ok());
}
}
fn transported(cut: &Cut) -> Cut {
let bytes = DotSet::from_witnessed(cut).to_bytes();
let decoded = DotSet::from_bytes(&bytes).expect("a canonical frame decodes");
let floor = Cut::floor_of(&decoded);
assert_eq!(
DotSet::from_witnessed(&floor),
decoded,
"the receiver proves gap-freedom before the cut-shaped role"
);
floor
}
#[test]
fn a_relay_of_subset_meets_serves_the_exact_watermark() {
let claims: [(u32, VersionVector); 4] = [
(1, vector(&[(1, 9), (2, 3), (3, 5), (4, 7)])),
(2, vector(&[(1, 4), (2, 8), (3, 6), (4, 2)])),
(3, vector(&[(1, 6), (2, 5), (3, 9), (4, 4)])),
(4, vector(&[(1, 8), (2, 2), (3, 7), (4, 9)])),
];
let mut direct = Stability::new([1, 2, 3, 4]);
for (member, claim) in &claims {
direct
.report_cut(*member, &transported(&Cut::from_witnessed(claim.clone())))
.unwrap();
}
let exact = direct.watermark();
assert_eq!(exact, vector(&[(1, 4), (2, 2), (3, 5), (4, 2)]));
assert!(direct.watermark_cut().is_some());
let left = transported(&Cut::from_witnessed(claims[0].1.clone()))
.meet(&transported(&Cut::from_witnessed(claims[1].1.clone())));
let right = transported(&Cut::from_witnessed(claims[2].1.clone()))
.meet(&transported(&Cut::from_witnessed(claims[3].1.clone())));
let mut relayed = Stability::new([1, 2, 3, 4]);
for member in [1u32, 2] {
assert!(relayed.watermark() <= exact, "safe at every prefix");
relayed.report_cut(member, &transported(&left)).unwrap();
}
for member in [3u32, 4] {
assert!(relayed.watermark() <= exact, "safe at every prefix");
relayed.report_cut(member, &transported(&right)).unwrap();
}
assert_eq!(
relayed.watermark(),
exact,
"a complete relay wave reads the exact global meet"
);
assert!(relayed.watermark_cut().is_some());
let mut epochs = Epochs::new([1, 2, 3, 4], NonZeroUsize::new(1).unwrap());
assert!(
epochs
.declare(d(1, 10), rank(3), &relayed, &Cut::bottom())
.is_ok(),
"the relayed tracker licenses a declaration"
);
for (member, claim) in &claims {
relayed
.report_cut(*member, &transported(&Cut::from_witnessed(claim.clone())))
.unwrap();
assert_eq!(relayed.watermark(), exact);
}
let mut bare = Stability::new([1, 2, 3, 4]);
for member in [1u32, 2] {
bare.report(member, left.as_vector()).unwrap();
}
for member in [3u32, 4] {
bare.report(member, right.as_vector()).unwrap();
}
assert_eq!(bare.watermark(), exact);
assert!(
bare.watermark_cut().is_none(),
"the bare door costs the witness"
);
}
fn arb_relay_claims() -> impl Strategy<Value = [VersionVector; 4]> {
prop::collection::vec(prop::collection::btree_map(1u32..=4, 1u64..=20, 0..=4), 4).prop_map(
|claims| {
let mut out: [VersionVector; 4] = array::from_fn(|_| VersionVector::new());
for (slot, counts) in out.iter_mut().zip(claims) {
for (station, count) in counts {
slot.observe(station, count);
}
}
out
},
)
}
proptest! {
#![proptest_config(ProptestConfig::with_cases(256))]
#[test]
fn prop_relayed_subset_meets_are_sound_at_every_prefix_and_exact_when_complete(
claims in arb_relay_claims(),
partition in prop::collection::vec(any::<bool>(), 4),
keys in prop::collection::vec(0u32..1_000_000, 8),
) {
let exact = claims
.iter()
.skip(1)
.fold(claims[0].clone(), |meet, claim| meet.meet(claim));
let group_meet = |flag: bool| {
claims
.iter()
.zip(&partition)
.filter(|(_, in_group)| **in_group == flag)
.map(|(claim, _)| transported(&Cut::from_witnessed(claim.clone())))
.fold(None::<Cut>, |meet, cut| {
Some(meet.map_or_else(|| cut.clone(), |held| held.meet(&cut)))
})
};
let meets = [group_meet(false), group_meet(true)];
let mut events: Vec<(u32, usize, bool)> = (0..8)
.map(|index| (keys[index], index % 4, index >= 4))
.collect();
events.sort_unstable();
let mut tracker = Stability::new([1, 2, 3, 4]);
let mut covered = [false; 4];
let mut complete_at: Option<usize> = None;
for (step, &(_, member, direct)) in events.iter().enumerate() {
let station = u32::try_from(member + 1).expect("small roster");
let report = if direct {
transported(&Cut::from_witnessed(claims[member].clone()))
} else {
meets[usize::from(partition[member])]
.clone()
.expect("the member's own group is never empty")
};
tracker.report_cut(station, &transported(&report)).unwrap();
covered[member] = true;
if complete_at.is_none() && covered.iter().all(|&seen| seen) {
complete_at = Some(step);
}
let watermark = tracker.watermark();
prop_assert!(watermark <= exact, "prefix watermark overshoots the meet");
if complete_at.is_some() {
prop_assert_eq!(watermark, exact.clone());
}
}
prop_assert!(tracker.watermark_cut().is_some() || events.is_empty());
}
}