extern crate alloc;
use core::num::NonZeroU32;
use crate::kairos::{Clock, LocalClock, TickCounter, VirtualTimeSource};
use alloc::vec::Vec;
fn run_len(len: u32) -> NonZeroU32 {
NonZeroU32::new(len).expect("test run lengths are nonzero")
}
#[test]
fn test_a_run_is_the_frozen_reading_mint_succession() {
let frozen = Clock::with_default_config(VirtualTimeSource::new(41), 3).unwrap();
let individually: Vec<_> = (0..5).map(|_| frozen.now(7u16)).collect();
let bulk = Clock::with_default_config(VirtualTimeSource::new(41), 3).unwrap();
let run = bulk.now_run(run_len(5), 7u16);
assert_eq!(run.len(), 5);
assert_eq!(run.iter().len(), 5, "the iterator is exact-sized");
let members: Vec<_> = run.iter().collect();
assert_eq!(members, individually);
assert_eq!(run.first(), individually[0]);
assert_eq!(run.last(), individually[4]);
for (index, &stamp) in (0u32..).zip(&individually) {
assert_eq!(run.get(index), Some(stamp));
}
assert_eq!(run.get(5), None, "reads past the reservation refuse");
assert_eq!(frozen.now(7u16), bulk.now(7u16));
}
#[test]
fn test_a_run_of_one_is_exactly_now() {
let single = Clock::with_default_config(TickCounter::new(), 2).unwrap();
let bulk = Clock::with_default_config(TickCounter::new(), 2).unwrap();
let minted = single.now(0u16);
let run = bulk.now_run(run_len(1), 0u16);
assert_eq!(run.first(), minted);
assert_eq!(run.last(), minted);
assert_eq!(run.len(), 1);
}
#[test]
fn test_the_next_mint_dominates_every_run_member() {
let clock = Clock::with_default_config(TickCounter::new(), 5).unwrap();
let run = clock.now_run(run_len(1_000), 0u16);
let next = clock.now(0u16);
assert!(next > run.last(), "the commitment is the run's last member");
for stamp in &run {
assert!(
next > stamp,
"no later mint may land inside the reservation"
);
}
}
#[test]
fn test_a_run_rolls_the_logical_ceiling_into_physical() {
let clock = Clock::with_default_config(VirtualTimeSource::new(100), 1).unwrap();
let width = u32::from(u16::MAX); let run = clock.now_run(run_len(width + 2), 0u16);
assert_eq!(run.first().physical(), 100);
assert_eq!(run.first().logical(), 0);
let last_in_unit = run.get(width - 1).unwrap();
assert_eq!(last_in_unit.physical(), 100);
assert_eq!(last_in_unit.logical(), u16::MAX - 1);
let rolled = run.get(width).unwrap();
assert_eq!(rolled.physical(), 101, "the sentinel rolls into physical");
assert_eq!(rolled.logical(), 0, "logical restarts after the roll");
assert!(rolled > last_in_unit);
assert_eq!(run.last(), run.get(width + 1).unwrap());
assert!(clock.now(0u16) > run.last());
}
#[test]
fn test_a_unit_crossing_run_reports_the_iterated_skews() {
let width = u32::from(u16::MAX);
let bulk = Clock::with_default_config(VirtualTimeSource::new(41), 3).unwrap();
let _ = bulk.now_run(run_len(width + 2), 0u16);
let single = Clock::with_default_config(VirtualTimeSource::new(41), 3).unwrap();
for _ in 0..u64::from(width) + 2 {
let _ = single.now(0u16);
}
let (bulk_stats, single_stats) = (bulk.stats(), single.stats());
assert_eq!(
bulk_stats.max_forward_skew_ns, single_stats.max_forward_skew_ns,
"one reservation reports the forward skew its mints would have"
);
assert_eq!(
bulk_stats.max_backward_skew_ns, single_stats.max_backward_skew_ns,
"one reservation reports the backward skew its mints would have"
);
assert_eq!(
bulk_stats.max_forward_skew_ns, 1,
"the crossing ran the committed physical one unit ahead"
);
let exact = Clock::with_default_config(VirtualTimeSource::new(41), 3).unwrap();
let _ = exact.now_run(run_len(width + 1), 0u16);
let twin = Clock::with_default_config(VirtualTimeSource::new(41), 3).unwrap();
for _ in 0..=u64::from(width) {
let _ = twin.now(0u16);
}
assert_eq!(
exact.stats().max_forward_skew_ns,
twin.stats().max_forward_skew_ns
);
assert_eq!(exact.stats().max_forward_skew_ns, 0);
}
#[test]
fn test_a_run_observes_skew_once() {
let source = VirtualTimeSource::new(50);
let driver = source.clone();
let clock = Clock::with_default_config(source, 1).unwrap();
let _ = clock.now(0u16);
driver.set(20); let _ = clock.now_run(run_len(64), 0u16);
assert_eq!(
clock.stats().max_backward_skew_ns,
30,
"one reading, one skew observation"
);
}
#[test]
fn test_local_clock_runs_agree_with_the_atomic_shell() {
let atomic = Clock::with_default_config(TickCounter::new(), 4).unwrap();
let local = LocalClock::new(TickCounter::new(), 4).unwrap();
let a = atomic.now_run(run_len(9), 3u16);
let b = local.now_run(run_len(9), 3u16);
assert_eq!(a, b, "one fold, two shells: identical reservations");
assert_eq!(atomic.now(3u16), local.now(3u16));
}