ai-rule-engine/tests/test_executor.py
root e39829fc4e feat(ai-rule-engine): 完成 MVP 所有批次实现
批次1: 项目结构 + SQLite 存储层 + 数据模型
批次2: REST API (http.server)
批次3: LLM 编译器 (支持 OpenAI/Anthropic)
批次4: RestrictedPython 规则执行器
批次5: 规则匹配器 + LLM Callback 兜底
批次6: 冲突检测器

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-11 22:19:42 +08:00

111 lines
3.2 KiB
Python

"""Tests for rule executor."""
import pytest
from rule_engine.executor import RuleExecutor, Sandbox, ExecutionTimeout
def test_executor_simple_rule():
"""验证简单规则执行。"""
executor = RuleExecutor()
code = '''
def rule(facts):
if facts.get("subscription") == "premium":
return {"action": "discount", "rate": 0.8}
return None
'''
# 匹配
result = executor.execute_rule(code, {"subscription": "premium", "age": 25})
assert result == {"action": "discount", "rate": 0.8}
# 不匹配
result = executor.execute_rule(code, {"subscription": "basic", "age": 25})
assert result is None
def test_executor_complex_condition():
"""验证复杂条件规则。"""
executor = RuleExecutor()
code = '''
def rule(facts):
age = facts.get("age", 0)
subscription = facts.get("subscription")
if subscription == "premium" and age >= 18:
return {"action": "approve"}
return {"action": "deny"}
'''
result = executor.execute_rule(code, {"subscription": "premium", "age": 25})
assert result["action"] == "approve"
result = executor.execute_rule(code, {"subscription": "premium", "age": 16})
assert result["action"] == "deny"
result = executor.execute_rule(code, {"subscription": "basic", "age": 25})
assert result["action"] == "deny"
def test_executor_validate_rule_code_valid():
"""验证合法代码通过检查。"""
executor = RuleExecutor()
code = 'def rule(facts):\n return None'
assert executor.validate_rule_code(code) is True
def test_executor_validate_rule_code_blocked_keyword():
"""验证危险关键字被拦截。"""
executor = RuleExecutor()
assert executor.validate_rule_code('def rule(facts):\n import os') is False
assert executor.validate_rule_code('def rule(facts):\n exec("")') is False
assert executor.validate_rule_code('def rule(facts):\n eval("")') is False
def test_executor_validate_rule_code_syntax_error():
"""验证语法错误被检测。"""
executor = RuleExecutor()
assert executor.validate_rule_code('def rule(facts):\n if .') is False
def test_executor_timeout():
"""验证执行超时。"""
executor = RuleExecutor(timeout_ms=100)
code = '''
def rule(facts):
# 死循环
while True:
pass
return None
'''
with pytest.raises(RuntimeError) as exc_info:
executor.execute_rule(code, {})
assert "timed out" in str(exc_info.value)
def test_sandbox_blocks_dangerous_operations():
"""验证沙箱拦截危险操作。"""
executor = RuleExecutor()
# 尝试访问受保护属性
code = '''
def rule(facts):
return __builtins__
'''
# 注意:实际 exec 中 __builtins__ 已被替换为白名单
# 所以不会返回真正的 builtins
def test_executor_nested_data():
"""验证嵌套数据结构处理。"""
executor = RuleExecutor()
code = '''
def rule(facts):
user = facts.get("user", {})
if user.get("subscription") == "premium" and user.get("active"):
return {"action": "allow"}
return None
'''
facts = {
"user": {
"subscription": "premium",
"active": True
}
}
result = executor.execute_rule(code, facts)
assert result["action"] == "allow"