use super::super::super::support::dot;
use crate::metis::{Composer, DotMap, DotSet, DotStore, Dotted};
use super::{Doc, add_under, assert_covered, dots};
#[test]
fn test_compose_assigns_the_first_dot_and_holds_it() {
let mut composer: Composer<Doc> = Composer::new(1);
assert_eq!(composer.station(), 1);
let (receipt, delta) = composer.compose(add_under(7));
assert_eq!(receipt, dot(1, 1));
assert!(delta.context().contains(receipt));
assert!(
delta
.store()
.get(&7)
.is_some_and(|held| held.contains(dot(1, 1)))
);
assert!(
composer
.state()
.store()
.get(&7)
.is_some_and(|held| held.contains(dot(1, 1)))
);
assert_eq!(composer.state().next_dot(1), dot(1, 2));
}
#[test]
fn test_a_run_write_composes_like_a_keystroke() {
extern crate alloc;
use crate::kairos::{Clock, TickCounter};
use crate::metis::{Anchor, Rhapsody};
let clock = Clock::with_default_config(TickCounter::new(), 1).unwrap();
let mut writer: Composer<Rhapsody> = Composer::new(1);
let run = clock.now_run(core::num::NonZeroU32::new(150).unwrap(), 0u16);
let (receipt, delta) = writer.compose(|assigned| {
let mut rhapsody = Rhapsody::new();
assert!(rhapsody.weave_run(assigned, Anchor::Origin, run));
(rhapsody, DotSet::new())
});
assert_eq!(receipt, dot(1, 1));
for k in 1..=150u64 {
assert!(
delta.context().contains(dot(1, k)),
"the delta covers the run"
);
}
assert!(
delta
.store()
.dots()
.all(|held| delta.context().contains(held)),
"the delta's context covers its store"
);
assert_eq!(
writer.state().next_dot(1),
dot(1, 151),
"the next assignment is fresh past the whole run"
);
assert_eq!(writer.state().store().order().len(), 150);
let mut reader: Composer<Rhapsody> = Composer::new(2);
let _ = reader.absorb(1, &delta);
assert_eq!(reader.state(), writer.state(), "one run delta converges");
}
#[test]
fn test_compose_calls_ascend_strictly() {
let mut composer: Composer<Doc> = Composer::new(1);
let (d1, first) = composer.compose(add_under(7));
let (d2, second) = composer.compose(add_under(7));
let (d3, third) = composer.compose(add_under(9));
assert_eq!((d1, d2, d3), (dot(1, 1), dot(1, 2), dot(1, 3)));
assert!(first.store().get(&7).is_some_and(|h| h.contains(dot(1, 1))));
assert!(
second
.store()
.get(&7)
.is_some_and(|h| h.contains(dot(1, 2)))
);
assert!(third.store().get(&9).is_some_and(|h| h.contains(dot(1, 3))));
}
#[test]
fn test_compose_after_retracting_everything_stays_fresh() {
let mut composer: Composer<Doc> = Composer::new(1);
let _ = composer.compose(add_under(7));
let observed = composer
.state()
.store()
.get(&7)
.cloned()
.unwrap_or_default();
let _ = composer.retract(observed);
assert!(composer.state().store().is_bottom());
let (_, after) = composer.compose(add_under(7));
assert!(
after
.store()
.get(&7)
.is_some_and(|held| held.contains(dot(1, 2)))
);
assert!(
!after
.store()
.get(&7)
.is_some_and(|held| held.contains(dot(1, 1)))
);
}
#[test]
fn test_compose_that_supersedes_is_covered() {
let mut composer: Composer<Doc> = Composer::new(1);
let _ = composer.compose(add_under(7));
let old = composer
.state()
.store()
.get(&7)
.cloned()
.unwrap_or_default();
let (_, delta) = composer.compose(move |assigned| {
let store = DotMap::singleton(7u8, dots(&[(assigned.station(), assigned.counter())]));
(store, old)
});
assert!(delta.context().contains(dot(1, 1)));
assert!(delta.context().contains(dot(1, 2)));
assert!(
delta
.store()
.get(&7)
.is_some_and(|held| held.contains(dot(1, 2)))
);
assert_covered(&delta);
let held = composer.state().store().get(&7).expect("the key survives");
assert!(held.contains(dot(1, 2)) && !held.contains(dot(1, 1)));
}
#[test]
fn test_retract_and_owed_deltas_are_covered() {
let mut composer: Composer<Doc> = Composer::new(1);
let _ = composer.compose(add_under(7));
let observed = composer
.state()
.store()
.get(&7)
.cloned()
.unwrap_or_default();
let retraction = composer.retract(observed);
assert_covered(&retraction);
let owed = composer.owed_to(&DotSet::new());
assert_covered(&owed);
assert_eq!(&owed, composer.state());
}
#[test]
fn test_compose_receipt_is_the_merged_dot_even_with_a_merge_around_the_call() {
let mut composer: Composer<Doc> = Composer::new(1);
let foreign = Dotted::from_store(DotMap::singleton(3u8, dots(&[(1, 1), (1, 2)])));
let _ = composer.absorb(9, &foreign);
let (receipt, delta) = composer.compose(add_under(7));
assert_eq!(
receipt,
dot(1, 3),
"the receipt is the true high-water successor"
);
assert!(
delta
.store()
.get(&7)
.is_some_and(|held| held.contains(receipt)),
"the store carries exactly the receipt dot"
);
assert!(
composer
.state()
.store()
.get(&7)
.is_some_and(|held| held.contains(dot(1, 3)))
);
}
#[test]
fn test_compose_super_equals_the_manual_read_then_compose() {
let mut manual: Composer<Doc> = Composer::new(1);
let mut facade: Composer<Doc> = Composer::new(1);
let _ = manual.compose(add_under(7));
let _ = facade.compose(add_under(7));
let observed = manual.state().store().get(&7).cloned().unwrap_or_default();
let (manual_dot, manual_delta) = manual.compose(move |assigned| {
(
DotMap::singleton(7u8, dots(&[(assigned.station(), assigned.counter())])),
observed,
)
});
let (facade_dot, facade_delta) = facade.compose_super(
|assigned| DotMap::singleton(7u8, dots(&[(assigned.station(), assigned.counter())])),
|held| held.get(&7).cloned().unwrap_or_default(),
);
assert_eq!(manual_dot, facade_dot);
assert_eq!(manual_delta, facade_delta);
assert_eq!(manual.state(), facade.state());
assert!(facade_delta.context().contains(dot(1, 1)));
assert!(facade_delta.context().contains(dot(1, 2)));
}