use any_spawner::Executor;
use reactive_graph::{actions::ArcAction, owner::Owner, traits::GetUntracked};
use std::sync::Arc;
use tokio::sync::Notify;
async fn tick_until(mut cond: impl FnMut() -> bool) {
for _ in 0..10_000 {
if cond() {
return;
}
Executor::tick().await;
}
panic!("condition was never satisfied within the tick budget");
}
#[tokio::test]
async fn older_dispatch_does_not_clobber_newer_result() {
_ = Executor::init_tokio();
let owner = Owner::new();
owner.set();
let gate = Arc::new(Notify::new());
let action = {
let gate = gate.clone();
ArcAction::<u32, u32>::new(move |n: &u32| {
let n = *n;
let gate = gate.clone();
async move {
if n == 1 {
gate.notified().await;
}
n
}
})
};
let value = action.value();
let input = action.input();
action.dispatch(1);
action.dispatch(2);
tick_until(|| value.get_untracked() == Some(2)).await;
assert_eq!(
value.get_untracked(),
Some(2),
"newer dispatch should have committed its value"
);
gate.notify_one();
tick_until(|| input.get_untracked().is_none()).await;
assert_eq!(
value.get_untracked(),
Some(2),
"stale dispatch must not overwrite the newer result"
);
}