extern crate alloc;
use alloc::vec::Vec;
use crate::metis::{Dot, DotSet, Dotted, Retired};
use proptest::prelude::*;
use super::super::{REPLICAS, Seq, arb_ops, condense_pair, run};
proptest! {
#[test]
fn prop_condense_under_an_honest_claim_preserves_order(ops in arb_ops()) {
let (live, record) = run(&ops);
let fold = live.iter().fold(Seq::new(), |acc, r| acc.merge(r));
let mut converged: Vec<Seq> = live.iter().map(|r| r.merge(&fold)).collect();
let orders_before: Vec<Vec<Dot>> =
converged.iter().map(|r| r.store().order()).collect();
let mut retired = DotSet::new();
for &dot in &record.expelled {
let _ = retired.insert(dot);
}
let retired = Retired::trust(retired);
for r in &mut converged {
let mut rhapsody = r.store().clone();
let _ = rhapsody.condense(&retired);
*r = Dotted::try_new(rhapsody, r.context().clone()).unwrap();
}
for (r, before) in converged.iter().zip(&orders_before) {
prop_assert_eq!(&r.store().order(), before);
for &dot in record.woven.keys() {
prop_assert_eq!(
r.store().woven().contains(dot),
r.store().locus(dot).is_some(),
);
}
}
let forward = converged.iter().fold(Seq::new(), |acc, r| acc.merge(r));
let backward = converged.iter().rev().fold(Seq::new(), |acc, r| acc.merge(r));
let forward_order = forward.store().order();
prop_assert_eq!(&forward_order, &backward.store().order());
prop_assert_eq!(&forward_order, &orders_before[0]);
for r in &converged {
prop_assert_eq!(&forward.merge(r).store().order(), &forward_order);
}
}
#[test]
fn prop_condense_commutes_with_merge(ops in arb_ops()) {
let (live, record) = run(&ops);
let fold = live.iter().fold(Seq::new(), |acc, r| acc.merge(r));
let converged: Vec<Seq> = live.iter().map(|r| r.merge(&fold)).collect();
let a = &converged[0];
let b = &converged[REPLICAS - 1];
let mut retired = DotSet::new();
for &dot in &record.expelled {
let _ = retired.insert(dot);
}
let retired = Retired::trust(retired);
let left = condense_pair(&a.merge(b), &retired);
let right = condense_pair(a, &retired).merge(&condense_pair(b, &retired));
prop_assert_eq!(left.store().order(), right.store().order());
}
#[test]
fn prop_monotone_claim_condense_is_idempotent(ops in arb_ops()) {
let (live, record) = run(&ops);
let fold = live.iter().fold(Seq::new(), |acc, r| acc.merge(r));
let converged = live[0].merge(&fold);
let expelled: Vec<Dot> = record.expelled.iter().copied().collect();
let mut r1 = DotSet::new();
let mut r2 = DotSet::new();
for (i, &dot) in expelled.iter().enumerate() {
let _ = r2.insert(dot);
if i % 2 == 0 {
let _ = r1.insert(dot);
}
}
let (r1, r2) = (Retired::trust(r1), Retired::trust(r2));
let staged = condense_pair(&condense_pair(&converged, &r1), &r2);
let one_shot = condense_pair(&converged, &r2);
prop_assert_eq!(staged.store().skeleton_len(), one_shot.store().skeleton_len());
prop_assert_eq!(staged.store().order(), one_shot.store().order());
}
}