extern crate alloc;
use alloc::vec::Vec;
use crate::metis::{Dot, DotStore};
use proptest::prelude::*;
use super::super::{REPLICAS, Seq, arb_ops_with_paste, reference_order, run};
proptest! {
#[test]
fn prop_replicas_converge_to_the_order_oracle(ops in arb_ops_with_paste()) {
let (live, record) = run(&ops);
let forward = live.iter().fold(Seq::new(), |acc, r| acc.merge(r));
let backward = live.iter().rev().fold(Seq::new(), |acc, r| acc.merge(r));
prop_assert_eq!(&forward, &backward);
for r in &live {
prop_assert_eq!(&forward.merge(r), &forward);
}
let expected = reference_order(&record);
let got = forward.store().order();
prop_assert_eq!(got, expected);
}
#[test]
fn prop_rhapsody_merge_from_agrees_with_merge(ops in arb_ops_with_paste()) {
let (live, _) = run(&ops);
for a in &live {
for b in &live {
let mut folded = a.clone();
folded.merge_from(b);
prop_assert_eq!(&folded, &a.merge(b));
prop_assert_eq!(folded.store().order(), a.merge(b).store().order());
}
}
}
#[test]
fn prop_order_is_fold_order_independent(
ops in arb_ops_with_paste(),
extra in prop::collection::vec(0usize..REPLICAS, 0..REPLICAS),
shuffle in Just((0..REPLICAS).collect::<Vec<usize>>()).prop_shuffle(),
) {
let (live, _) = run(&ops);
let fold = |seq: &[usize]| -> Vec<Dot> {
let mut acc = Seq::new();
for &i in seq {
acc = acc.merge(&live[i]);
}
acc.store().order()
};
let mut permuted = shuffle;
permuted.extend(extra);
let a = fold(&(0..REPLICAS).collect::<Vec<_>>());
let b = fold(&permuted);
prop_assert_eq!(a, b);
}
#[test]
fn prop_skeleton_is_grow_only(ops in arb_ops_with_paste()) {
let (live, record) = run(&ops);
let forward = live.iter().fold(Seq::new(), |acc, r| acc.merge(r));
for &dot in record.woven.keys() {
prop_assert!(forward.store().locus(dot).is_some());
}
prop_assert_eq!(forward.store().skeleton_len(), record.woven.len());
}
#[test]
fn prop_visible_is_woven_minus_expelled(ops in arb_ops_with_paste()) {
let (live, record) = run(&ops);
let forward = live.iter().fold(Seq::new(), |acc, r| acc.merge(r));
let mut want: Vec<Dot> = record
.woven
.keys()
.copied()
.filter(|dot| !record.expelled.contains(dot))
.collect();
want.sort_unstable();
let mut got: Vec<Dot> = forward.store().dots().collect();
got.sort_unstable();
prop_assert_eq!(got, want);
}
}