use effect_rs::{Effect, Exit, Ref, Runtime};
use std::time::Duration;
#[test]
fn test_ref_update() {
let rt = Runtime::new();
let counter = Ref::new(0);
let program = counter.update(|x| x + 1).flat_map(move |val| {
assert_eq!(val, 1);
counter.get()
});
let result = rt.block_on(program, ());
match result {
Exit::Success(val) => assert_eq!(val, 1),
Exit::Failure(_) => panic!("Expected success"),
}
}
#[test]
fn test_ref_concurrent_updates() {
let rt = Runtime::new();
let counter = Ref::new(0);
let counter_p = counter.clone();
let program = Effect::succeed(Vec::<effect_rs::Fiber<(), i32>>::new())
.flat_map(move |_| {
let mut effects = Vec::new();
for _ in 0..10 {
let counter = counter_p.clone();
let eff = Effect::async_effect(move || async {
tokio::time::sleep(Duration::from_millis(10)).await;
()
})
.flat_map(move |_| counter.update(|x| x + 1))
.fork();
effects.push(eff);
}
effects
.into_iter()
.fold(Effect::succeed(Vec::new()), |acc, eff| {
acc.flat_map(move |mut fibers| {
eff.map(move |fiber| {
fibers.push(fiber);
fibers
})
})
})
})
.flat_map(|fibers| {
fibers.into_iter().fold(Effect::succeed(()), |acc, fiber| {
acc.flat_map(move |_| {
Effect::async_effect(move || async move { fiber.join().await })
.flat_map(Effect::done)
.map(|_| ())
})
})
});
let result = rt.block_on(program, ());
match result {
Exit::Success(_) => {}
Exit::Failure(_) => panic!("Expected success"),
}
let check = rt.block_on(counter.get(), ());
match check {
Exit::Success(val) => assert_eq!(val, 10), Exit::Failure(_) => panic!("Expected success"),
}
}