endr 0.9.0

endr: append-only replicated objects
Documentation
use std::collections::HashSet;

use proptest::prelude::*;
use serde_derive::{Deserialize, Serialize};

use super::{CausalSet, CausalSetItem};

#[derive(Clone, Serialize, Deserialize, Debug)]
struct TestItem {
    id: usize,
    data: usize,
    prev: HashSet<usize>,
}

impl CausalSetItem for TestItem {
    type ID = usize;

    fn id(&self) -> Self::ID {
        self.id
    }

    fn prev(&self) -> HashSet<&Self::ID> {
        self.prev.iter().collect()
    }
}

fn arb_linear_set(n_items: u32) -> BoxedStrategy<Vec<TestItem>> {
    let mut items = Vec::new();

    for i in 0..n_items {
        let mut prev = HashSet::new();
        if i > 0 {
            prev.insert((i - 1) as usize);
        }
        items.push(TestItem {
            id: i as usize,
            data: i as usize,
            prev,
        });
    }

    Just(items).boxed()
}

fn arb_randomly_connected_set(n_items: u32) -> BoxedStrategy<Vec<TestItem>> {
    Just(n_items)
        .prop_perturb(move |_n, mut rng| {
            let mut items = Vec::new();

            for i in 0..n_items {
                let mut prev = HashSet::new();
                if i > 0 {
                    let n_prev = rng.gen_range(0..i.min(4));
                    for _p in 0..n_prev {
                        prev.insert(rng.gen_range(0..i as usize));
                    }
                }
                items.push(TestItem {
                    id: i as usize,
                    data: i as usize,
                    prev,
                });
            }

            items
        })
        .boxed()
}

proptest! {
    #[test]
    fn linear_items_in_any_order_causes_no_disconnected(items in arb_linear_set(20).prop_shuffle()) {
        let mut set = CausalSet::new();
        // println!("Start");
        for item in items {
            // println!("Inserting item {:?}", item);
            set.insert(item);
            // println!("Disconnected: {:?}", set.disconnected_items);
        }

        assert!(!set.has_disconnected());
    }

    #[test]
    fn randomly_connected_items_in_any_order_causes_no_disconnected(items in arb_randomly_connected_set(200).prop_shuffle()) {
        let mut set = CausalSet::new();

        for item in items {
            // println!("Inserting item {:?}", item);
            set.insert(item);
        }

        assert!(!set.has_disconnected());
    }
}