extern crate alloc;
use alloc::collections::BTreeSet;
use alloc::string::String;
use super::super::super::support::dot;
use crate::metis::{Dot, DotFun, DotSet, DotStore};
use proptest::prelude::*;
use super::{arb_seed, covered, value_for};
proptest! {
#[test]
fn prop_survivor_law_is_exact_with_values(a in arb_seed(), b in arb_seed()) {
let ca = covered(&a);
let cb = covered(&b);
let merged = ca.store().causal_merge(ca.context(), cb.store(), cb.context());
let a_dots: BTreeSet<Dot> = ca.store().dots().collect();
let b_dots: BTreeSet<Dot> = cb.store().dots().collect();
let merged_dots: BTreeSet<Dot> = merged.dots().collect();
for station in 0u32..4 {
for counter in 1u64..9 {
let probe = dot(station, counter);
let in_a = a_dots.contains(&probe);
let in_b = b_dots.contains(&probe);
let survives = (in_a && (in_b || !cb.context().contains(probe)))
|| (in_b && (in_a || !ca.context().contains(probe)));
prop_assert_eq!(merged_dots.contains(&probe), survives);
if survives {
let got = merged.get(probe).expect("a survivor carries content");
prop_assert_eq!(got, &value_for(station, counter));
}
}
}
}
#[test]
fn prop_causal_merge_is_commutative(a in arb_seed(), b in arb_seed()) {
let ca = covered(&a);
let cb = covered(&b);
let ab = ca.store().causal_merge(ca.context(), cb.store(), cb.context());
let ba = cb.store().causal_merge(cb.context(), ca.store(), ca.context());
prop_assert_eq!(ab, ba);
}
#[test]
fn prop_causal_merge_is_associative(a in arb_seed(), b in arb_seed(), c in arb_seed()) {
let ca = covered(&a);
let cb = covered(&b);
let cc = covered(&c);
let bc = cb.store().causal_merge(cb.context(), cc.store(), cc.context());
let bc_ctx = cb.context().merge(cc.context());
let left = ca.store().causal_merge(ca.context(), &bc, &bc_ctx);
let ab = ca.store().causal_merge(ca.context(), cb.store(), cb.context());
let ab_ctx = ca.context().merge(cb.context());
let right = ab.causal_merge(&ab_ctx, cc.store(), cc.context());
prop_assert_eq!(left, right);
}
#[test]
fn prop_causal_merge_is_idempotent(a in arb_seed()) {
let ca = covered(&a);
let merged = ca.store().causal_merge(ca.context(), ca.store(), ca.context());
prop_assert_eq!(&merged, ca.store());
}
#[test]
fn prop_bottom_is_the_identity(a in arb_seed()) {
let ca = covered(&a);
let bottom = DotFun::<String>::new();
let empty = DotSet::new();
let right = ca.store().causal_merge(ca.context(), &bottom, &empty);
prop_assert_eq!(&right, ca.store());
let left = bottom.causal_merge(&empty, ca.store(), ca.context());
prop_assert_eq!(&left, ca.store());
}
}