#![allow(clippy::unwrap_used)]
use entelix_core::{ExecutionContext, Result};
use entelix_runnable::{
Runnable, RunnableExt, RunnableLambda, RunnablePassthrough, RunnableSequence,
};
#[tokio::test]
async fn pipe_chains_two_lambdas() {
let ctx = ExecutionContext::new();
let double = RunnableLambda::new(|x: i32, _ctx| async move { Ok::<_, _>(x * 2) });
let add_one = RunnableLambda::new(|x: i32, _ctx| async move { Ok::<_, _>(x + 1) });
let chain = double.pipe(add_one);
let result: i32 = chain.invoke(3, &ctx).await.unwrap();
assert_eq!(result, 7); }
#[tokio::test]
async fn passthrough_returns_input_unchanged() -> Result<()> {
let ctx = ExecutionContext::new();
let pt: RunnablePassthrough = RunnablePassthrough;
let out: String = pt.invoke("hello".to_owned(), &ctx).await?;
assert_eq!(out, "hello");
Ok(())
}
#[tokio::test]
async fn batch_default_runs_sequentially() -> Result<()> {
let ctx = ExecutionContext::new();
let triple = RunnableLambda::new(|x: i32, _ctx| async move { Ok::<_, _>(x * 3) });
let outs = triple.batch(vec![1, 2, 3], &ctx).await?;
assert_eq!(outs, vec![3, 6, 9]);
Ok(())
}
#[tokio::test]
async fn batch_short_circuits_on_cancellation() {
let ctx = ExecutionContext::new();
let lambda = RunnableLambda::new(|x: i32, _ctx| async move { Ok::<_, _>(x * 2) });
ctx.cancellation().cancel();
let res = lambda.batch(vec![1, 2, 3], &ctx).await;
assert!(matches!(res, Err(entelix_core::Error::Cancelled)));
}
#[tokio::test]
async fn three_stage_pipe_typechecks() -> Result<()> {
let ctx = ExecutionContext::new();
let to_string = RunnableLambda::new(|x: i32, _ctx| async move { Ok::<_, _>(format!("{x}")) });
let to_len = RunnableLambda::new(|s: String, _ctx| async move { Ok::<_, _>(s.len()) });
let to_bool = RunnableLambda::new(|n: usize, _ctx| async move { Ok::<_, _>(n > 0) });
let chain: RunnableSequence<i32, usize, bool> = to_string.pipe(to_len).pipe(to_bool);
let out: bool = chain.invoke(42, &ctx).await?;
assert!(out);
Ok(())
}