minerva 0.2.0

Causal ordering for distributed systems
use crate::metis::Dotted;

use super::super::{Seq, clock, delete, insert};
use super::{claim, condense};

#[test]
fn test_condense_monotone_claim_is_idempotent() {
    let build = || {
        let mut r: Seq = Dotted::new();
        let clk = clock(1);
        let d0 = insert(&mut r, &clk, 1, None);
        let d1 = insert(&mut r, &clk, 1, Some(d0));
        let d2 = insert(&mut r, &clk, 1, Some(d1));
        let d3 = insert(&mut r, &clk, 1, Some(d2));
        delete(&mut r, d1);
        delete(&mut r, d2);
        delete(&mut r, d3);
        (r, d1, d2, d3)
    };

    let (mut staged, d1, d2, d3) = build();
    let s1 = condense(&mut staged, &claim(&[d2, d3]));
    assert_eq!(s1, 2);
    let s2 = condense(&mut staged, &claim(&[d1, d2, d3]));
    assert_eq!(s2, 1);

    let (mut one_shot, _, _, _) = build();
    let o = condense(&mut one_shot, &claim(&[d1, d2, d3]));
    assert_eq!(o, 3);

    assert_eq!(
        staged.store().skeleton_len(),
        one_shot.store().skeleton_len()
    );
    assert_eq!(staged.store().order(), one_shot.store().order());
    for &dot in &[d1, d2, d3] {
        assert!(staged.store().locus(dot).is_none());
        assert!(one_shot.store().locus(dot).is_none());
    }
}

#[test]
fn test_condense_visible_guard_leaves_a_named_visible_dot_untouched() {
    let mut r: Seq = Dotted::new();
    let clk = clock(1);
    let d0 = insert(&mut r, &clk, 1, None);
    let d1 = insert(&mut r, &clk, 1, Some(d0));

    let excised = condense(&mut r, &claim(&[d0, d1]));
    assert_eq!(excised, 0);
    assert!(r.store().locus(d0).is_some());
    assert!(r.store().locus(d1).is_some());
    assert_eq!(r.store().order(), [d0, d1]);
}

#[test]
fn test_condense_gossip_cycle_relearns_then_reexcises() {
    let mut a: Seq = Dotted::new();
    let clk = clock(1);
    let d0 = insert(&mut a, &clk, 1, None);
    let d1 = insert(&mut a, &clk, 1, Some(d0));
    delete(&mut a, d1);
    let order = a.store().order();

    let peer = a.clone();
    let retired = claim(&[d1]);

    let first = condense(&mut a, &retired);
    assert_eq!(first, 1);
    assert!(a.store().locus(d1).is_none());
    assert_eq!(a.store().order(), order);

    a = a.merge(&peer);
    assert!(a.store().locus(d1).is_some());
    assert!(!a.store().is_visible(d1));
    assert_eq!(a.store().order(), order);

    let second = condense(&mut a, &retired);
    assert_eq!(second, first);
    assert!(a.store().locus(d1).is_none());
    assert_eq!(a.store().order(), order);
}

#[test]
fn test_condense_is_idempotent_with_the_same_claim() {
    let mut r: Seq = Dotted::new();
    let clk = clock(1);
    let d0 = insert(&mut r, &clk, 1, None);
    let d1 = insert(&mut r, &clk, 1, Some(d0));
    let d2 = insert(&mut r, &clk, 1, Some(d1));
    delete(&mut r, d1);
    delete(&mut r, d2);
    let retired = claim(&[d1, d2]);

    let first = condense(&mut r, &retired);
    assert_eq!(first, 2);
    let second = condense(&mut r, &retired);
    assert_eq!(second, 0);
    assert_eq!(r.store().order(), [d0]);
}