#![cfg(feature = "instrumentation")]
use lazily::{Context, QueueCell};
#[test]
fn unsubscribed_ops_do_not_derive_or_schedule() {
let ctx = Context::new();
let q: QueueCell<i32> = QueueCell::new(&ctx);
q.try_push(&ctx, 0).unwrap();
ctx.reset_instrumentation();
const OPS: i32 = 1000;
for i in 0..OPS {
q.try_push(&ctx, i).unwrap();
q.try_pop(&ctx).unwrap();
}
let snap = ctx.instrumentation_snapshot();
assert_eq!(
snap.slot_recomputes, 0,
"unsubscribed ops must derive no reader-kind value"
);
assert_eq!(
snap.effect_queue_pushes, 0,
"unsubscribed ops must schedule no effect (store-without-cascade)"
);
assert_eq!(
snap.node_allocations, 0,
"steady-state ops must allocate no new graph nodes"
);
}
#[test]
fn burst_writes_coalesce_to_one_recompute() {
for burst in [1usize, 8, 64, 512] {
let ctx = Context::new();
let q: QueueCell<i32> = QueueCell::new(&ctx);
assert_eq!(q.len(&ctx), 0);
ctx.reset_instrumentation();
for i in 0..burst {
q.try_push(&ctx, i as i32).unwrap();
}
assert_eq!(
ctx.instrumentation_snapshot().slot_recomputes,
0,
"a write-only burst must not derive the len Slot"
);
assert_eq!(q.len(&ctx), burst);
assert_eq!(
ctx.instrumentation_snapshot().slot_recomputes,
1,
"burst of {burst} writes + 1 read must recompute len exactly once"
);
}
}
#[test]
fn store_without_cascade_skips_flush_but_stays_glitch_free() {
let ctx = Context::new();
let cell = ctx.cell(0i32);
let doubled = ctx.computed(move |ctx| ctx.get_cell(&cell) * 2);
assert_eq!(ctx.get(&doubled), 0);
ctx.reset_instrumentation();
for v in 1..=100 {
ctx.set_cell(&cell, v);
}
assert_eq!(
ctx.instrumentation_snapshot().effect_queue_pushes,
0,
"writes with no Effect in the dependent cone must schedule no effect"
);
assert_eq!(ctx.get(&doubled), 200);
}