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_excises_a_sterile_retired_tombstone() {
    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, d2);
    let before = r.store().order();

    let excised = condense(&mut r, &claim(&[d2]));
    assert_eq!(excised, 1);
    assert_eq!(r.store().order(), before);
    assert!(r.store().locus(d2).is_none());
    assert_eq!(r.store().skeleton_len(), 2);
}

#[test]
fn test_condense_spares_a_tombstone_with_a_visible_child() {
    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);
    assert_eq!(r.store().order(), [d0, d2]);

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

#[test]
fn test_condense_spares_a_tombstone_with_a_merely_woven_child() {
    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);
    assert_eq!(r.store().order(), [d0]);

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

#[test]
fn test_condense_excises_a_dead_unbranched_chain_tip_first() {
    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);
    assert_eq!(r.store().order(), [d0]);

    let excised = condense(&mut r, &claim(&[d1, d2, d3]));
    assert_eq!(excised, 3);
    assert_eq!(r.store().order(), [d0]);
    assert!(r.store().locus(d1).is_none());
    assert!(r.store().locus(d2).is_none());
    assert!(r.store().locus(d3).is_none());
    assert_eq!(r.store().skeleton_len(), 1);
}

#[test]
fn test_condense_stops_at_a_non_retired_dot_in_the_chain() {
    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);

    let excised = condense(&mut r, &claim(&[d2, d3]));
    assert_eq!(excised, 2);
    assert!(r.store().locus(d1).is_some());
    assert!(r.store().locus(d2).is_none());
    assert!(r.store().locus(d3).is_none());
}