extern crate alloc;
use alloc::vec::Vec;
use super::super::super::support::dot;
use super::{Doc, add, dots, remove_observed};
use crate::metis::{DotMap, DotSet, DotStore, Dotted};
#[test]
fn test_write_flow_lands_the_dot() {
let mut doc = Doc::new();
let (_, fresh) = add(&mut doc, 1, 7);
assert_eq!(fresh, dot(1, 1));
assert!(
doc.store()
.get(&7)
.is_some_and(|held| held.contains(dot(1, 1)))
);
assert!(doc.context().contains(dot(1, 1)));
assert_eq!(doc.next_dot(1), dot(1, 2));
}
#[test]
fn test_removal_does_not_resurrect_through_a_stale_peer() {
let mut a = Doc::new();
let _ = add(&mut a, 1, 7);
let mut b = Doc::new();
b = b.merge(&a); let _ = remove_observed(&mut a, 7);
assert!(a.store().get(&7).is_none());
let rejoined = a.merge(&b);
assert!(rejoined.store().get(&7).is_none());
assert_eq!(rejoined, b.merge(&a)); let fresh = Doc::new().merge(&a);
assert!(fresh.store().get(&7).is_none());
assert!(fresh.context().contains(dot(1, 1)));
}
#[test]
fn test_concurrent_add_survives_concurrent_removal() {
let mut a = Doc::new();
let _ = add(&mut a, 1, 7);
let mut b = Doc::new();
b = b.merge(&a);
let _ = remove_observed(&mut b, 7); let _ = add(&mut a, 1, 7); let merged = a.merge(&b);
let held = merged.store().get(&7).expect("the concurrent add survives");
assert!(!held.contains(dot(1, 1)));
assert!(held.contains(dot(1, 2)));
}
#[test]
fn test_next_dot_survives_removal() {
let mut doc = Doc::new();
let _ = add(&mut doc, 1, 7);
let _ = remove_observed(&mut doc, 7);
assert!(doc.store().is_bottom()); assert_eq!(doc.next_dot(1), dot(1, 2)); }
#[test]
fn test_key_vanishes_when_every_dot_is_superseded() {
let mut doc = Doc::new();
let _ = add(&mut doc, 1, 7);
let _ = add(&mut doc, 1, 9);
let _ = remove_observed(&mut doc, 7);
assert!(doc.store().get(&7).is_none());
assert_eq!(doc.store().len(), 1);
let keys: Vec<u8> = doc.store().iter().map(|(&key, _)| key).collect();
assert_eq!(keys, [9]);
}
#[test]
fn test_nested_composition_removes_at_the_leaf() {
type Nested = Dotted<DotMap<u8, DotMap<u8, DotSet>>>;
let mut doc = Nested::new();
let fresh = doc.next_dot(1);
let inner = DotMap::singleton(2u8, dots(&[(fresh.station(), fresh.counter())]));
let delta = Dotted::from_store(DotMap::singleton(1u8, inner));
doc = doc.merge(&delta);
assert!(
doc.store()
.get(&1)
.and_then(|inner| inner.get(&2))
.is_some_and(|held| held.contains(dot(1, 1)))
);
let removal = Dotted::from_context(dots(&[(1, 1)]));
doc = doc.merge(&removal);
assert!(doc.store().is_bottom());
assert_eq!(doc.next_dot(1), dot(1, 2));
}