minerva 0.2.0

Causal ordering for distributed systems
//! Declaration, confirmation, and roster validation cases.

use super::*;
use crate::metis::Vouched;

#[test]
fn a_declaration_needs_the_watermark_witness() {
    let mut epochs = machine();
    let mut stability = tracker();
    for station in ROSTER {
        stability.report_cut(station, &top()).unwrap();
    }
    stability.report(1, top().as_vector()).unwrap();

    let refused = epochs
        .declare(
            d(1, 1),
            Kairos::new(1, 0, 1, 0u16),
            &stability,
            &Cut::bottom(),
        )
        .expect_err("no witnessed cut, no declaration");
    assert_eq!(refused, EpochRefusal::Unwitnessed);
}

#[test]
fn a_declaration_address_must_be_fresh_above_its_cut() {
    let mut epochs = machine();
    let mut stability = tracker();
    for station in ROSTER {
        stability.report_cut(station, &top()).unwrap();
    }
    assert_eq!(
        epochs.declare(
            d(1, 9),
            Kairos::new(9, 0, 1, 0u16),
            &stability,
            &Cut::bottom()
        ),
        Err(EpochRefusal::StaleDeclaration {
            dot: d(1, 9),
            ceiling: 9,
        })
    );
}

#[test]
fn confirmation_must_cover_the_declaration_address() {
    let bottom = cut(&[]);
    let mut stability = tracker();
    for station in ROSTER {
        stability.report_cut(station, &bottom).unwrap();
    }
    let mut epochs = machine();
    let declaration = epochs
        .declare(
            d(1, 1),
            Kairos::new(1, 0, 1, 0u16),
            &stability,
            &Cut::bottom(),
        )
        .unwrap();
    assert_eq!(
        epochs.confirm(declaration.address(), &Vouched::trust(1, bottom.clone())),
        Err(EpochRefusal::ConfirmationDoesNotCover {
            epoch: declaration.address(),
            station: 1,
            covered: 0,
        })
    );
    assert_eq!(
        epochs.adopt(1, 0, &stability),
        Err(EpochRefusal::Unconfirmed)
    );
}

#[test]
fn off_roster_declarations_cannot_enter_the_window() {
    let bottom = cut(&[]);
    let mut stability = tracker();
    for station in ROSTER {
        stability.report_cut(station, &bottom).unwrap();
    }
    let mut epochs = machine();
    assert_eq!(
        epochs.declare(
            d(9, 1),
            Kairos::new(1, 0, 9, 0u16),
            &stability,
            &Cut::bottom()
        ),
        Err(EpochRefusal::UnknownDeclarationStation { station: 9 })
    );

    let mut foreign_stability = Stability::new([9]);
    foreign_stability.report_cut(9, &bottom).unwrap();
    let foreign = Epochs::new([9], NonZeroUsize::new(1).unwrap())
        .declare(
            d(9, 1),
            Kairos::new(1, 0, 9, 0u16),
            &foreign_stability,
            &Cut::bottom(),
        )
        .unwrap();
    assert_eq!(
        epochs.deliver(foreign, &stability, &Cut::bottom()),
        Err(EpochRefusal::UnknownDeclarationStation { station: 9 })
    );
    assert_eq!(epochs.candidates().count(), 0);
}