extern crate alloc;
use crate::kairos::{Clock, TickCounter};
use crate::metis::{CausalIdeal, Dot, Event, Producer, VersionVector};
use alloc::vec::Vec;
use proptest::prelude::*;
#[track_caller]
pub(super) fn dot(station: u32, counter: u64) -> Dot {
Dot::from_parts(station, counter).expect("test literal names the non-dot counter zero")
}
pub(super) fn vv(pairs: &[(u32, u64)]) -> VersionVector {
let mut v = VersionVector::new();
for &(station, count) in pairs {
v.observe(station, count);
}
v
}
pub(super) fn arb_vv() -> impl Strategy<Value = VersionVector> {
prop::collection::vec((0u32..6, 0u64..8), 0..8).prop_map(|pairs| vv(&pairs))
}
pub(super) type Payload = u32;
pub(super) fn drain(buf: &mut CausalIdeal<Payload>) -> Vec<Payload> {
let mut released = Vec::new();
while let Some(payload) = buf.pop_ready() {
released.push(payload);
}
released
}
pub(super) fn deliverable(event: &Event<Payload>, delivered: &VersionVector) -> bool {
let sender = event.stamp.station_id();
if event.deps.get(sender) != delivered.get(sender).saturating_add(1) {
return false;
}
event
.deps
.iter()
.all(|(station, count)| station == sender || count <= delivered.get(station))
}
pub(super) fn build_history(
num_stations: usize,
steps: &[(usize, Vec<usize>)],
) -> Vec<Event<Payload>> {
let mut producers: Vec<Producer<Clock<TickCounter>>> = (1..=num_stations)
.map(|id| {
let station_id = u32::try_from(id).unwrap();
let clock = Clock::with_default_config(TickCounter::new(), station_id).unwrap();
Producer::new(clock)
})
.collect();
let mut history: Vec<Event<Payload>> = Vec::new();
for &(producer, ref learn_from) in steps {
for event in &history {
let source = event.stamp.station_id() as usize - 1;
if source != producer && learn_from.contains(&source) {
producers[producer].observe(event);
}
}
let payload = u32::try_from(history.len()).unwrap();
history.push(producers[producer].produce(0u16, payload));
}
history
}
pub(super) fn arb_history() -> impl Strategy<Value = Vec<Event<Payload>>> {
(1usize..=4).prop_flat_map(|num_stations| {
let step = (
0..num_stations,
prop::collection::vec(0..num_stations, 0..num_stations),
);
prop::collection::vec(step, 1..14)
.prop_map(move |steps| build_history(num_stations, &steps))
})
}
pub(super) fn perm_of(len: usize) -> impl Strategy<Value = Vec<usize>> {
Just((0..len).collect::<Vec<usize>>()).prop_shuffle()
}