minerva 0.2.0

Causal ordering for distributed systems
extern crate alloc;

use crate::kairos::{Clock, Kairos, TickCounter, TimeSource};

#[test]
fn test_after_causality() {
    let clock = Clock::with_default_config(TickCounter::new(), 1).unwrap();
    let remote_t = Kairos::new(100, 0, 2, 10u16);
    let local_t = clock.after(remote_t, 20u16);

    assert!(local_t > remote_t, "Timestamp must be after the remote one");
    assert_eq!(
        local_t.physical(),
        100,
        "Physical time should jump to remote's time"
    );
    assert_eq!(local_t.logical(), 1, "Logical time should be incremented");
    assert_eq!(local_t.kairotic(), 20, "Kairotic should be set correctly");
    assert_eq!(local_t.station_id(), 1);
}

#[test]
fn test_after_with_same_physical_time() {
    let time_source = TickCounter::new();
    let _ = time_source.now(); // Advance to 1.
    let clock = Clock::with_default_config(time_source, 1).unwrap();

    let _t1 = clock.now(0u16); // physical: 1, logical: 0, time source now at 2.
    let remote_t = Kairos::new(2, 5, 2, 10u16);
    let t2 = clock.after(remote_t, 20u16); // time source returns 2.

    assert_eq!(t2.physical(), 2);
    assert_eq!(t2.logical(), 6); // max(0, 5) + 1.
    assert_eq!(t2.kairotic(), 20);
}

#[test]
fn test_after_with_past_physical_time() {
    let time_source = TickCounter::new();
    let _ = time_source.now(); // Advance time to 1.
    let _ = time_source.now(); // Advance time to 2.
    let clock = Clock::with_default_config(time_source, 1).unwrap();

    let local_t1 = clock.now(0u16); // physical: 2, logical: 0.
    let remote_t = Kairos::new(0, 0, 2, 10u16);
    let local_t2 = clock.after(remote_t, 20u16);

    assert!(local_t2 > local_t1);
    assert_eq!(
        local_t2.physical(),
        3,
        "Physical time should follow the local time source"
    );
    assert_eq!(local_t2.kairotic(), 20);
}

#[test]
fn test_logical_overflow() {
    let clock = Clock::with_default_config(TickCounter::new(), 1).unwrap();
    let mut t = Kairos::new(5, u16::MAX - 2, 1, 10u16);

    t = clock.after(t, 20u16);
    assert_eq!(t.physical(), 5);
    assert_eq!(t.logical(), u16::MAX - 1);
    assert_eq!(t.kairotic(), 20);

    t = clock.after(t, 30u16);
    assert_eq!(
        t.physical(),
        6,
        "Physical time should increment on logical overflow"
    );
    assert_eq!(t.logical(), 0, "Logical time should reset to 0 on overflow");
    assert_eq!(t.kairotic(), 30);
}