minerva 0.2.0

Causal ordering for distributed systems
use core::fmt;
use core::mem::{align_of, size_of};

use crate::kairos::Kairos;
use crate::metis::{Causal, Event, Gate, Ideal, Released, VersionVector};

struct OpaqueGate;

#[derive(Default)]
struct Progress {
    advances: u32,
    sender: u32,
    dep: u64,
}

impl Gate for OpaqueGate {
    type Dep = u64;
    type Progress = Progress;

    fn deliverable(_progress: &Self::Progress, _sender: u32, dep: &Self::Dep) -> bool {
        *dep == 7
    }

    fn advance(progress: &mut Self::Progress, sender: u32, dep: &Self::Dep) {
        progress.advances += 1;
        progress.sender = sender;
        progress.dep = *dep;
    }

    fn stale(_progress: &Self::Progress, _sender: u32, _dep: &Self::Dep) -> bool {
        false
    }
}

#[test]
fn released_preserves_event_layout() {
    assert_eq!(
        size_of::<Released<u8, Causal>>(),
        size_of::<Event<u8, VersionVector>>()
    );
    assert_eq!(
        align_of::<Released<u8, Causal>>(),
        align_of::<Event<u8, VersionVector>>()
    );
}

#[test]
fn release_witnesses_the_occurrence_used_to_advance() {
    let stamp = Kairos::new(11, 0, 4, 0u16);
    let mut ideal: Ideal<_, OpaqueGate> = Ideal::default();
    ideal.insert(Event {
        stamp,
        deps: 7,
        payload: 19u8,
    });

    let released = ideal.pop_ready_event().expect("the gate admits dep 7");

    assert_eq!(released.stamp(), stamp);
    assert_eq!(*released.deps(), 7);
    assert_eq!(*released.payload(), 19);
    assert_eq!(ideal.pending_len(), 0);
    assert_eq!(ideal.progress().advances, 1);
    assert_eq!(ideal.progress().sender, 4);
    assert_eq!(ideal.progress().dep, 7);
}

#[test]
fn debug_depends_on_event_data_not_the_gate_marker() {
    fn assert_debug<T: fmt::Debug>() {}

    assert_debug::<Released<u8, OpaqueGate>>();
}