minerva 0.2.0

Causal ordering for distributed systems
extern crate alloc;

use super::super::super::d;
use super::super::{Seq, clock, woven};
use crate::metis::dot::RawDot;
use crate::metis::{Anchor, Dot, Dotted, Locus, Rhapsody};
use alloc::vec::Vec;

#[test]
fn test_weave_refuses_duplicate_and_zero() {
    let mut rhapsody = Rhapsody::new();
    let rank = clock(1).now(0u16);
    let locus = Locus {
        anchor: Anchor::Origin,
        rank,
    };
    // The non-dot counter zero no longer reaches this door: the identity
    // type carries the law, so the refusal moved to construction and the
    // plane stays empty because nothing was offered (ruling R-91).
    assert!(Dot::from_parts(1, 0).is_err());
    assert_eq!(rhapsody.skeleton_len(), 0);

    assert!(rhapsody.weave(d(1, 1), locus));
    assert_eq!(rhapsody.skeleton_len(), 1);

    assert!(!rhapsody.weave(d(1, 1), locus));
    assert_eq!(rhapsody.skeleton_len(), 1);
    assert_eq!(rhapsody.visible_len(), 1);
}

#[test]
fn test_dangling_anchor_is_accepted_but_unreachable() {
    let clk = clock(1);
    let mut rhapsody = Rhapsody::new();
    let child_rank = clk.now(0u16);
    assert!(rhapsody.weave(
        d(1, 2),
        Locus {
            anchor: Anchor::After(RawDot {
                station: 1,
                counter: 1
            }),
            rank: child_rank,
        }
    ));
    assert!(rhapsody.is_visible(d(1, 2)));
    assert_eq!(rhapsody.order(), Vec::<Dot>::new());
}

#[test]
fn test_dangling_then_repaired() {
    let mut replica: Seq = Dotted::new();
    let clk = clock(1);

    let anchor_rank = clk.now(0u16);
    let child_rank = clk.now(0u16);
    let child_delta = woven(
        d(1, 2),
        Locus {
            anchor: Anchor::After(RawDot {
                station: 1,
                counter: 1,
            }),
            rank: child_rank,
        },
    );
    replica = replica.merge(&child_delta);
    assert!(replica.store().is_visible(d(1, 2)));
    assert_eq!(replica.store().order(), Vec::<Dot>::new());

    let anchor_delta = woven(
        d(1, 1),
        Locus {
            anchor: Anchor::Origin,
            rank: anchor_rank,
        },
    );
    replica = replica.merge(&anchor_delta);
    assert_eq!(replica.store().order(), [d(1, 1), d(1, 2)]);
}

#[cfg(feature = "instrumentation")]
#[test]
fn test_profile_counts_each_structural_term() {
    let clk = clock(1);
    let mut rhapsody = Rhapsody::new();
    let mut previous: Option<Dot> = None;
    for index in 1..=65 {
        let dot = d(1, index);
        assert!(rhapsody.weave(
            dot,
            Locus {
                anchor: previous.map_or(Anchor::Origin, |dot| Anchor::After(dot.into())),
                rank: clk.now(0u16),
            },
        ));
        previous = Some(dot);
    }

    let profile = rhapsody.profile();
    assert_eq!(profile.skeleton_dots, 65);
    assert_eq!(profile.explicit_loci, 2);
    assert_eq!(profile.placed_slots, 65);
    assert_eq!(profile.order_fragments, 2);
    assert_eq!(profile.visible_pages, 2);
    assert_eq!(profile.visible_exceptions, 0);
    assert_eq!(profile.woven_exceptions, 0);
}

#[test]
fn test_owed_delta_heals_a_tombstone_the_retract_outran() {
    // The S190 gate-review finding, at the bare sequence seam: a pure-context
    // retract delta conveys coverage of a woven dot WITHOUT its locus, so a
    // peer it outruns holds the dot as seen-and-dropped while never having
    // held its place. The peer's survivor context is therefore no proxy for
    // its recording knowledge, and an owed delta whose skeleton fragment
    // were filtered by that context would strand every later element
    // anchored to the tombstone (unreachable at the peer, placed at the
    // writer, forever). The cure is the S113 delta_for correction one
    // coordinate over: `novel_to` ships the skeleton whole.
    use crate::metis::Composer;

    let clk = clock(1);
    let mut writer: Composer<Rhapsody> = Composer::new(1);
    let mut peer: Composer<Rhapsody> = Composer::new(2);

    // d woven, then retracted, then e woven hanging after d's tombstone.
    let (d, _weave_d) = writer.compose(|dot| {
        let mut delta = Rhapsody::new();
        assert!(delta.weave(
            dot,
            Locus {
                anchor: Anchor::Origin,
                rank: clk.now(0u16),
            }
        ));
        (delta, crate::metis::DotSet::new())
    });
    let mut superseded = crate::metis::DotSet::new();
    assert!(superseded.insert(d));
    let retract = writer.retract(superseded);
    let (e, _weave_e) = writer.compose(|dot| {
        let mut delta = Rhapsody::new();
        assert!(delta.weave(
            dot,
            Locus {
                anchor: Anchor::After(d.into()),
                rank: clk.now(0u16),
            }
        ));
        (delta, crate::metis::DotSet::new())
    });

    // The retract outran everything: it is the only delta the peer got.
    let _ = peer.absorb(1, &retract);

    // Anti-entropy catch-up must now be exactly as good as the full state.
    let owed = writer.owed_to(peer.state().context());
    let _ = peer.absorb(1, &owed);

    assert_eq!(
        writer.state(),
        peer.state(),
        "the owed delta heals the outrun tombstone"
    );
    assert!(peer.state().store().is_reachable(e));
    assert_eq!(writer.state().store().order(), peer.state().store().order());
}

#[test]
fn test_witnessed_owed_delta_heals_the_outrun_and_ships_only_the_owed_loci() {
    // The witnessed owed read against the same outrun scenario: the peer's
    // recording witness (its own maintained `woven()`) genuinely does not
    // claim the tombstone the retract outran, so the witnessed fragment
    // carries it, and the heal holds where the S190 counterexample showed a
    // COVERAGE-filtered fragment would strand it forever. Possession claimed
    // directly is what coverage could not prove; the fragment is bounded by
    // the owed residual instead of the document.
    use crate::metis::{Composer, DotSet};

    let clk = clock(1);
    let mut writer: Composer<Rhapsody> = Composer::new(1);
    let mut peer: Composer<Rhapsody> = Composer::new(2);

    let (d, _weave_d) = writer.compose(|dot| {
        let mut delta = Rhapsody::new();
        assert!(delta.weave(
            dot,
            Locus {
                anchor: Anchor::Origin,
                rank: clk.now(0u16),
            }
        ));
        (delta, DotSet::new())
    });
    let mut superseded = DotSet::new();
    assert!(superseded.insert(d));
    let retract = writer.retract(superseded);
    let (e, _weave_e) = writer.compose(|dot| {
        let mut delta = Rhapsody::new();
        assert!(delta.weave(
            dot,
            Locus {
                anchor: Anchor::After(d.into()),
                rank: clk.now(0u16),
            }
        ));
        (delta, DotSet::new())
    });

    // The retract outran everything; the peer's witness claims nothing.
    let _ = peer.absorb(1, &retract);
    let owed = writer.owed_to_witnessed(peer.state().context(), peer.state().store().woven());
    assert_eq!(
        owed.store().skeleton_len(),
        2,
        "the witnessed fragment carries exactly the two unclaimed loci"
    );
    let _ = peer.absorb(1, &owed);
    assert_eq!(
        writer.state(),
        peer.state(),
        "the witnessed owed delta heals the outrun tombstone"
    );
    assert!(peer.state().store().is_reachable(e));

    // Steady state: one more keystroke, and the next witnessed exchange
    // ships exactly one locus, never the document (the arc-10 point).
    let (f, _weave_f) = writer.compose(|dot| {
        let mut delta = Rhapsody::new();
        assert!(delta.weave(
            dot,
            Locus {
                anchor: Anchor::After(e.into()),
                rank: clk.now(0u16),
            }
        ));
        (delta, DotSet::new())
    });
    let owed = writer.owed_to_witnessed(peer.state().context(), peer.state().store().woven());
    assert_eq!(
        owed.store().skeleton_len(),
        1,
        "one keystroke behind owes one locus through the witnessed read"
    );
    let _ = peer.absorb(1, &owed);
    assert_eq!(writer.state(), peer.state());
    assert!(peer.state().store().is_visible(f));

    // Fully caught up: the witnessed fragment carries no recording state at
    // all, where the bare read re-ships the whole skeleton per probe.
    let owed = writer.owed_to_witnessed(peer.state().context(), peer.state().store().woven());
    assert_eq!(owed.store().skeleton_len(), 0);
    assert_eq!(
        writer
            .owed_to(peer.state().context())
            .store()
            .skeleton_len(),
        3,
        "the bare read still ships the plane whole, its documented contract"
    );
}

#[test]
fn test_an_over_claiming_witness_cannot_corrupt_the_fragment() {
    // The gate review's counterexample: the peer's context is empty (so the
    // live dot is survivor novelty) while its recording witness claims that
    // very dot, a claim no honest witness can make (an honest woven set is
    // covered by its own context, and a dot outside the peer's context is
    // outside its woven set). The witnessed fragment must still carry the
    // locus for every visible dot it ships (the visible-subset-of-skeleton
    // value invariant the wire frame refuses violations of), so the
    // over-claim starves the claimant of tombstone loci only, never of the
    // places for the content it is being handed.
    use crate::metis::{Composer, DotSet};

    let clk = clock(1);
    let mut writer: Composer<Rhapsody> = Composer::new(1);
    let (d, _weave_d) = writer.compose(|dot| {
        let mut delta = Rhapsody::new();
        assert!(delta.weave(
            dot,
            Locus {
                anchor: Anchor::Origin,
                rank: clk.now(0u16),
            }
        ));
        (delta, DotSet::new())
    });

    let mut over_claim = DotSet::new();
    assert!(over_claim.insert(d));
    let owed = writer.owed_to_witnessed(&DotSet::new(), &over_claim);
    assert!(owed.store().is_visible(d));
    assert!(
        owed.store().locus(d).is_some(),
        "a shipped visible dot rides with its locus, whatever the witness claims"
    );

    let mut peer: Composer<Rhapsody> = Composer::new(2);
    let _ = peer.absorb(1, &owed);
    assert!(peer.state().store().is_reachable(d));
    assert_eq!(writer.state().store().order(), peer.state().store().order());
}