use effect_rs::{Cause, Effect, Exit, Runtime};
use std::sync::{Arc, Mutex};
#[test]
fn test_effect_success_composition() {
let rt = Runtime::new();
let program: Effect<(), (), i32> = Effect::succeed(10)
.map(|x: i32| x * 2)
.flat_map(|x| Effect::succeed(x + 5));
let result = rt.block_on(program, ());
match result {
Exit::Success(val) => assert_eq!(val, 25),
Exit::Failure(_) => panic!("Expected success"),
}
}
#[test]
fn test_effect_failure_propagation() {
let rt = Runtime::new();
let program: Effect<(), &'static str, i32> = Effect::fail("error").map(|x: i32| x * 2);
let result = rt.block_on(program, ());
match result {
Exit::Success(_) => panic!("Expected failure"),
Exit::Failure(cause) => match cause {
Cause::Fail(e) => assert_eq!(e, "error"),
_ => panic!("Expected Fail cause"),
},
}
}
#[test]
fn test_async_effect() {
let rt = Runtime::new();
let program: Effect<(), (), i32> = Effect::async_effect(|| async {
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
42
});
let result = rt.block_on(program, ());
match result {
Exit::Success(val) => assert_eq!(val, 42),
Exit::Failure(_) => panic!("Expected success"),
}
}
#[test]
fn test_acquire_release() {
let rt = Runtime::new();
let released = Arc::new(Mutex::new(false));
let released_clone = released.clone();
let program: Effect<(), (), i32> = Effect::acquire_release(Effect::succeed(10), move |_, _| {
let released = released_clone.clone();
Effect::<(), (), ()>::async_effect(move || async move {
let mut guard = released.lock().unwrap();
*guard = true;
})
});
let result = rt.block_on(program, ());
match result {
Exit::Success(val) => assert_eq!(val, 10),
Exit::Failure(_) => panic!("Expected success"),
}
assert!(*released.lock().unwrap(), "Finalizer did not run");
}