use langchainrust::{
GraphBuilder, START, END,
AgentState, StateUpdate,
};
#[tokio::test]
async fn test_recursion_limit_respected() {
let compiled = GraphBuilder::<AgentState>::new()
.add_node_fn("loop_node", |state| Ok(StateUpdate::full(state.clone())))
.add_edge(START, "loop_node")
.add_edge("loop_node", "loop_node") .compile()
.unwrap()
.with_recursion_limit(5);
let result = compiled.invoke(AgentState::new("test".to_string())).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_default_recursion_limit() {
let compiled = GraphBuilder::<AgentState>::new()
.add_node_fn("a", |state| Ok(StateUpdate::full(state.clone())))
.add_node_fn("b", |state| Ok(StateUpdate::full(state.clone())))
.add_edge(START, "a")
.add_edge("a", "b")
.add_edge("b", END)
.compile()
.unwrap();
let result = compiled.invoke(AgentState::new("test".to_string())).await.unwrap();
assert_eq!(result.recursion_count, 2);
}
#[tokio::test]
async fn test_custom_recursion_limit_allows_valid_depth() {
let compiled = GraphBuilder::<AgentState>::new()
.add_node_fn("n1", |state| Ok(StateUpdate::full(state.clone())))
.add_node_fn("n2", |state| Ok(StateUpdate::full(state.clone())))
.add_node_fn("n3", |state| Ok(StateUpdate::full(state.clone())))
.add_node_fn("n4", |state| Ok(StateUpdate::full(state.clone())))
.add_node_fn("n5", |state| Ok(StateUpdate::full(state.clone())))
.add_edge(START, "n1")
.add_edge("n1", "n2")
.add_edge("n2", "n3")
.add_edge("n3", "n4")
.add_edge("n4", "n5")
.add_edge("n5", END)
.compile()
.unwrap()
.with_recursion_limit(10);
let result = compiled.invoke(AgentState::new("test".to_string())).await.unwrap();
assert_eq!(result.recursion_count, 5);
}
#[tokio::test]
async fn test_low_recursion_limit_fails_valid_graph() {
let compiled = GraphBuilder::<AgentState>::new()
.add_node_fn("n1", |state| Ok(StateUpdate::full(state.clone())))
.add_node_fn("n2", |state| Ok(StateUpdate::full(state.clone())))
.add_node_fn("n3", |state| Ok(StateUpdate::full(state.clone())))
.add_edge(START, "n1")
.add_edge("n1", "n2")
.add_edge("n2", "n3")
.add_edge("n3", END)
.compile()
.unwrap()
.with_recursion_limit(2);
let result = compiled.invoke(AgentState::new("test".to_string())).await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_graph_reaches_end_before_limit() {
let compiled = GraphBuilder::<AgentState>::new()
.add_node_fn("single", |state| {
let mut s = state.clone();
s.set_output("done".to_string());
Ok(StateUpdate::full(s))
})
.add_edge(START, "single")
.add_edge("single", END)
.compile()
.unwrap()
.with_recursion_limit(100);
let result = compiled.invoke(AgentState::new("test".to_string())).await.unwrap();
assert_eq!(result.recursion_count, 1);
assert_eq!(result.final_state.output, Some("done".to_string()));
}