triblespace-core 0.36.0

The triblespace core implementation.
use proptest::collection::vec;
use proptest::prelude::*;
use triblespace_core::patch::{Entry, IdentitySchema, PATCH};

type TestPatch = PATCH<8, IdentitySchema, ()>;

fn arb_key() -> impl Strategy<Value = [u8; 8]> {
    prop::array::uniform8(any::<u8>())
}

fn arb_patch(max: usize) -> impl Strategy<Value = TestPatch> {
    vec(arb_key(), 0..max).prop_map(|keys| {
        let mut patch = TestPatch::new();
        for k in &keys {
            patch.insert(&Entry::new(k));
        }
        patch
    })
}

proptest! {
    // ── Insert / lookup ────────────────────────────────────────────────

    #[test]
    fn insert_then_has_prefix(key in arb_key()) {
        let mut patch = TestPatch::new();
        patch.insert(&Entry::new(&key));
        prop_assert!(patch.has_prefix(&key));
        prop_assert_eq!(patch.len(), 1);
    }

    #[test]
    fn insert_idempotent(key in arb_key()) {
        let mut patch = TestPatch::new();
        patch.insert(&Entry::new(&key));
        patch.insert(&Entry::new(&key));
        prop_assert_eq!(patch.len(), 1);
    }

    #[test]
    fn remove_then_absent(key in arb_key()) {
        let mut patch = TestPatch::new();
        patch.insert(&Entry::new(&key));
        patch.remove(&key);
        prop_assert!(!patch.has_prefix(&key));
        prop_assert_eq!(patch.len(), 0);
    }

    // ── Set algebra ────────────────────────────────────────────────────

    #[test]
    fn union_commutative(a in arb_patch(15), b in arb_patch(15)) {
        let mut ab = a.clone();
        ab.union(b.clone());
        let mut ba = b;
        ba.union(a);
        prop_assert_eq!(ab, ba);
    }

    #[test]
    fn union_idempotent(a in arb_patch(15)) {
        let mut aa = a.clone();
        aa.union(a.clone());
        prop_assert_eq!(a, aa);
    }

    #[test]
    fn union_identity(a in arb_patch(15)) {
        let mut result = a.clone();
        result.union(TestPatch::new());
        prop_assert_eq!(a, result);
    }

    #[test]
    fn intersect_commutative(a in arb_patch(15), b in arb_patch(15)) {
        let ab = a.intersect(&b);
        let ba = b.intersect(&a);
        prop_assert_eq!(ab, ba);
    }

    #[test]
    fn intersect_idempotent(a in arb_patch(15)) {
        let aa = a.intersect(&a);
        prop_assert_eq!(a, aa);
    }

    #[test]
    fn difference_self_is_empty(a in arb_patch(15)) {
        let diff = a.difference(&a);
        prop_assert!(diff.is_empty());
    }

    #[test]
    fn difference_empty_is_self(a in arb_patch(15)) {
        let empty = TestPatch::new();
        let diff = a.difference(&empty);
        prop_assert_eq!(a, diff);
    }

    #[test]
    fn union_then_difference(a in arb_patch(10), b in arb_patch(10)) {
        let mut union = a.clone();
        union.union(b.clone());
        let diff = union.difference(&b);
        let expected = a.difference(&b);
        prop_assert_eq!(expected, diff);
    }

    #[test]
    fn intersect_subset_of_both(a in arb_patch(15), b in arb_patch(15)) {
        let inter = a.intersect(&b);
        for key in inter.iter() {
            prop_assert!(a.has_prefix(key));
            prop_assert!(b.has_prefix(key));
        }
    }

    // ── Iteration ──────────────────────────────────────────────────────

    #[test]
    fn iter_len_consistent(a in arb_patch(20)) {
        prop_assert_eq!(a.len() as usize, a.iter().count());
    }

    #[test]
    fn iter_ordered_is_sorted(a in arb_patch(20)) {
        let keys: Vec<[u8; 8]> = a.iter_ordered().copied().collect();
        for pair in keys.windows(2) {
            prop_assert!(pair[0] <= pair[1],
                "iter_ordered not sorted: {:?} > {:?}", pair[0], pair[1]);
        }
    }

    #[test]
    fn iter_and_iter_ordered_same_elements(a in arb_patch(20)) {
        let mut unordered: Vec<[u8; 8]> = a.iter().copied().collect();
        let mut ordered: Vec<[u8; 8]> = a.iter_ordered().copied().collect();
        unordered.sort();
        ordered.sort();
        prop_assert_eq!(unordered, ordered);
    }

    // ── Equality ─────────────────────────────────────────────────────

    #[test]
    fn clone_is_equal(a in arb_patch(15)) {
        let b = a.clone();
        prop_assert_eq!(a, b);
    }

    #[test]
    fn union_order_independent_equality(a in arb_patch(10), b in arb_patch(10)) {
        let mut ab = a.clone();
        ab.union(b.clone());
        let mut ba = b;
        ba.union(a);
        prop_assert_eq!(ab, ba);
    }
}