use cranpose_core::{NodeId, PackedU64};
use super::{LayoutSync, MAX_PENDING, SemanticsLayoutLog, record_layout_change};
fn synced(log: &SemanticsLayoutLog) -> (LayoutSync, Vec<NodeId>) {
let mut changed = Vec::new();
let sync = log.begin_sync(&mut changed);
(sync, changed)
}
#[test]
fn nothing_is_recorded_before_a_tree_reads_the_log() {
let log = SemanticsLayoutLog::default();
let mut stamp = PackedU64::default();
log.record(NodeId(7), &mut stamp);
let (sync, changed) = synced(&log);
assert!(!sync.continuous, "the first reader walks the whole tree");
assert!(changed.is_empty());
}
#[test]
fn each_node_is_recorded_once_between_reads() {
let log = SemanticsLayoutLog::default();
synced(&log);
let (mut first, mut second) = (PackedU64::default(), PackedU64::default());
log.record(NodeId(1), &mut first);
log.record(NodeId(1), &mut first);
log.record(NodeId(2), &mut second);
let (sync, changed) = synced(&log);
assert!(sync.continuous);
assert_eq!(changed, vec![NodeId(1), NodeId(2)]);
log.record(NodeId(1), &mut first);
assert_eq!(
synced(&log).1,
vec![NodeId(1)],
"a node changing again after a read is recorded again"
);
}
#[test]
fn an_overflowing_log_stops_recording_and_starts_a_new_epoch() {
let log = SemanticsLayoutLog::default();
let (before, _) = synced(&log);
let mut stamps = vec![PackedU64::default(); MAX_PENDING + 1];
for (id, stamp) in stamps.iter_mut().enumerate() {
log.record(NodeId(id), stamp);
}
let mut late = PackedU64::default();
log.record(NodeId(99_999), &mut late);
let (sync, changed) = synced(&log);
assert!(!sync.continuous, "the reader walks the whole tree again");
assert_ne!(sync.epoch, before.epoch);
assert!(changed.is_empty());
assert!(synced(&log).0.continuous, "the next read tracks again");
}
#[test]
fn changes_are_recorded_in_the_current_app_context_only_while_armed() {
let _app_context = crate::render_state::app_context_test_scope();
let mut stamp = PackedU64::default();
record_layout_change(NodeId(3), &mut stamp);
let drain = || {
crate::render_state::with_current_semantics_layout_log(synced).map(|(_, changed)| changed)
};
assert_eq!(drain(), Some(Vec::new()), "an unarmed log records nothing");
record_layout_change(NodeId(3), &mut stamp);
assert_eq!(drain(), Some(vec![NodeId(3)]));
}