//! 条件表达式引擎 — 用于 DAG 边上的条件判断 //! //! TODO: 实现完整的条件表达式解析与求值 use serde_json::Value; /// 条件表达式求值器 pub struct ConditionEngine; impl ConditionEngine { /// 求值条件表达式 /// /// 当前仅支持 "true"/"false" 字面量。未识别的表达式 **默认 false**(保守拒绝), /// 而非默认 true——条件分支写错或引擎未实现时不应该静默放行。 /// TODO: 实现完整的表达式解析(JSON Path / 数值比较 / contains / 逻辑组合)。 pub fn evaluate(expr: &str, _context: &Value) -> anyhow::Result { let trimmed = expr.trim(); if trimmed == "true" { return Ok(true); } if trimmed == "false" { return Ok(false); } // TODO: 实现如下语法: // - "$.status == 'completed'" — JSON Path 比较 // - "$.count > 10" — 数值比较 // - "$.tags contains 'ai'" — 包含检查 // - "and/or/not" — 逻辑组合 tracing::warn!("条件表达式引擎尚未完整实现,表达式未识别默认 false: {}", expr); Ok(false) } } #[cfg(test)] mod tests { use super::*; use serde_json::json; fn ctx() -> Value { // 当前实现未使用 context,但保持传入以对齐签名 json!({}) } #[test] fn test_true_literal_returns_true() { assert_eq!(ConditionEngine::evaluate("true", &ctx()).unwrap(), true); } #[test] fn test_false_literal_returns_false() { assert_eq!(ConditionEngine::evaluate("false", &ctx()).unwrap(), false); } #[test] fn test_unsupported_expression_defaults_to_false() { // 尚未实现的语法:表达式非 true/false 字面量时默认 false(保守拒绝,不静默放行) assert_eq!( ConditionEngine::evaluate("$.status == 'completed'", &ctx()).unwrap(), false ); } #[test] fn test_whitespace_is_trimmed() { // trimmed() 去除首尾空白后再与字面量比较 assert_eq!( ConditionEngine::evaluate(" true ", &ctx()).unwrap(), true ); assert_eq!( ConditionEngine::evaluate("\tfalse\n", &ctx()).unwrap(), false ); } #[test] fn test_empty_string_defaults_to_false() { assert_eq!(ConditionEngine::evaluate("", &ctx()).unwrap(), false); assert_eq!(ConditionEngine::evaluate(" ", &ctx()).unwrap(), false); } #[test] fn test_case_sensitive_not_matched() { // 字面量比较区分大小写:True/False 既非 "true" 也非 "false",默认 false assert_eq!(ConditionEngine::evaluate("True", &ctx()).unwrap(), false); assert_eq!(ConditionEngine::evaluate("FALSE", &ctx()).unwrap(), false); } #[test] fn test_arbitrary_string_defaults_to_false() { assert_eq!(ConditionEngine::evaluate("yes", &ctx()).unwrap(), false); assert_eq!(ConditionEngine::evaluate("1", &ctx()).unwrap(), false); assert_eq!(ConditionEngine::evaluate("completed", &ctx()).unwrap(), false); } }