use cano::prelude::*;
use std::borrow::Cow;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum Step {
Route,
PathA,
PathB,
Done,
}
struct InherentRouter;
#[task::router(state = Step)]
impl InherentRouter {
async fn route(&self, _res: &Resources) -> Result<TaskResult<Step>, CanoError> {
Ok(TaskResult::Single(Step::PathA))
}
}
#[test]
fn inherent_router_has_default_config() {
assert_eq!(
RouterTask::<Step>::config(&InherentRouter)
.retry_mode
.max_attempts(),
4
);
}
#[test]
fn inherent_router_has_default_name() {
assert!(
RouterTask::<Step>::name(&InherentRouter).contains("InherentRouter"),
"default name should contain the type name"
);
}
#[tokio::test]
async fn inherent_router_route_works() {
let res = Resources::new();
let result = RouterTask::route(&InherentRouter, &res).await.unwrap();
assert_eq!(result, TaskResult::Single(Step::PathA));
}
#[tokio::test]
async fn inherent_router_task_run_works() {
let res = Resources::new();
let result = Task::run(&InherentRouter, &res).await.unwrap();
assert_eq!(result, TaskResult::Single(Step::PathA));
}
struct InherentCustomRouter;
#[task::router(state = Step)]
impl InherentCustomRouter {
fn config(&self) -> TaskConfig {
TaskConfig::minimal()
}
fn name(&self) -> Cow<'static, str> {
Cow::Borrowed("my-inherent-router")
}
async fn route(&self, _res: &Resources) -> Result<TaskResult<Step>, CanoError> {
Ok(TaskResult::Single(Step::Done))
}
}
#[test]
fn inherent_custom_config_override() {
assert_eq!(
RouterTask::<Step>::config(&InherentCustomRouter)
.retry_mode
.max_attempts(),
1
);
}
#[test]
fn inherent_custom_name_override() {
assert_eq!(
RouterTask::<Step>::name(&InherentCustomRouter),
"my-inherent-router"
);
}
#[test]
fn inherent_companion_task_forwards_config() {
assert_eq!(
Task::config(&InherentCustomRouter)
.retry_mode
.max_attempts(),
1
);
}
#[test]
fn inherent_companion_task_forwards_name() {
assert_eq!(Task::name(&InherentCustomRouter), "my-inherent-router");
}
struct InherentSplitRouter;
#[task::router(state = Step)]
impl InherentSplitRouter {
async fn route(&self, _res: &Resources) -> Result<TaskResult<Step>, CanoError> {
Ok(TaskResult::Split(vec![Step::PathA, Step::PathB]))
}
}
#[tokio::test]
async fn inherent_router_can_return_split() {
let res = Resources::new();
let result = Task::run(&InherentSplitRouter, &res).await.unwrap();
assert_eq!(result, TaskResult::Split(vec![Step::PathA, Step::PathB]));
}
struct TraitRouter;
#[task::router]
impl RouterTask<Step> for TraitRouter {
async fn route(&self, _res: &Resources) -> Result<TaskResult<Step>, CanoError> {
Ok(TaskResult::Single(Step::PathA))
}
}
#[tokio::test]
async fn trait_form_route_works() {
let res = Resources::new();
let result = RouterTask::route(&TraitRouter, &res).await.unwrap();
assert_eq!(result, TaskResult::Single(Step::PathA));
}
#[tokio::test]
async fn trait_form_companion_task_run_works() {
let res = Resources::new();
let result = Task::run(&TraitRouter, &res).await.unwrap();
assert_eq!(result, TaskResult::Single(Step::PathA));
}
#[tokio::test]
async fn inherent_router_as_dyn_task() {
use std::sync::Arc;
let router: Arc<dyn Task<Step>> = Arc::new(InherentRouter);
let res = Resources::new();
let result = Task::run(router.as_ref(), &res).await.unwrap();
assert_eq!(result, TaskResult::Single(Step::PathA));
}
struct PathATask;
#[task(state = Step)]
impl PathATask {
async fn run_bare(&self) -> Result<TaskResult<Step>, CanoError> {
Ok(TaskResult::Single(Step::Done))
}
}
#[tokio::test]
async fn inherent_router_integrates_with_workflow() {
let workflow = Workflow::bare()
.register(Step::Route, InherentRouter)
.register(Step::PathA, PathATask)
.add_exit_state(Step::Done);
let result = workflow
.orchestrate(Step::Route, CancellationToken::disabled())
.await
.unwrap();
assert_eq!(result, Step::Done);
}
#[tokio::test]
async fn trait_router_integrates_with_workflow() {
let workflow = Workflow::bare()
.register(Step::Route, TraitRouter)
.register(Step::PathA, PathATask)
.add_exit_state(Step::Done);
let result = workflow
.orchestrate(Step::Route, CancellationToken::disabled())
.await
.unwrap();
assert_eq!(result, Step::Done);
}