mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-11 01:34:45 +08:00
Fixes a critical bug in the from_runnable_config() method where falsy values (like False, 0, and empty strings) were being incorrectly filtered out, causing configuration fields to revert to their default values. The fix changes the filter condition from if v to if v is not None, ensuring only None values are skipped.
183 lines
6.1 KiB
Python
183 lines
6.1 KiB
Python
# Copyright (c) 2025 Bytedance Ltd. and/or its affiliates
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
import sys
|
|
import types
|
|
|
|
from src.config.configuration import Configuration
|
|
|
|
# Patch sys.path so relative import works
|
|
|
|
# Patch Resource for import
|
|
mock_resource = type("Resource", (), {})
|
|
|
|
# Patch src.rag.retriever.Resource for import
|
|
|
|
module_name = "src.rag.retriever"
|
|
if module_name not in sys.modules:
|
|
retriever_mod = types.ModuleType(module_name)
|
|
retriever_mod.Resource = mock_resource
|
|
sys.modules[module_name] = retriever_mod
|
|
|
|
# Relative import of Configuration
|
|
|
|
|
|
def test_default_configuration():
|
|
config = Configuration()
|
|
assert config.resources == []
|
|
assert config.max_plan_iterations == 1
|
|
assert config.max_step_num == 3
|
|
assert config.max_search_results == 3
|
|
assert config.mcp_settings is None
|
|
|
|
|
|
def test_from_runnable_config_with_config_dict(monkeypatch):
|
|
config_dict = {
|
|
"configurable": {
|
|
"max_plan_iterations": 5,
|
|
"max_step_num": 7,
|
|
"max_search_results": 10,
|
|
"mcp_settings": {"foo": "bar"},
|
|
}
|
|
}
|
|
config = Configuration.from_runnable_config(config_dict)
|
|
assert config.max_plan_iterations == 5
|
|
assert config.max_step_num == 7
|
|
assert config.max_search_results == 10
|
|
assert config.mcp_settings == {"foo": "bar"}
|
|
|
|
|
|
def test_from_runnable_config_with_env_override(monkeypatch):
|
|
monkeypatch.setenv("MAX_PLAN_ITERATIONS", "9")
|
|
monkeypatch.setenv("MAX_STEP_NUM", "11")
|
|
config_dict = {
|
|
"configurable": {
|
|
"max_plan_iterations": 2,
|
|
"max_step_num": 3,
|
|
"max_search_results": 4,
|
|
}
|
|
}
|
|
config = Configuration.from_runnable_config(config_dict)
|
|
# Environment variables take precedence and are strings
|
|
assert config.max_plan_iterations == "9"
|
|
assert config.max_step_num == "11"
|
|
assert config.max_search_results == 4 # not overridden
|
|
# Clean up
|
|
monkeypatch.delenv("MAX_PLAN_ITERATIONS")
|
|
monkeypatch.delenv("MAX_STEP_NUM")
|
|
|
|
|
|
def test_from_runnable_config_with_none_and_falsy(monkeypatch):
|
|
"""Test that None values are skipped but falsy values (0, False, empty string) are preserved."""
|
|
config_dict = {
|
|
"configurable": {
|
|
"max_plan_iterations": None, # None should be skipped, use default
|
|
"max_step_num": 0, # 0 is valid, should be preserved
|
|
"max_search_results": "", # Empty string should be preserved
|
|
}
|
|
}
|
|
config = Configuration.from_runnable_config(config_dict)
|
|
# None values should fall back to defaults
|
|
assert config.max_plan_iterations == 1
|
|
# Falsy but valid values should be preserved
|
|
assert config.max_step_num == 0
|
|
assert config.max_search_results == ""
|
|
|
|
|
|
def test_from_runnable_config_with_no_config():
|
|
config = Configuration.from_runnable_config()
|
|
assert config.max_plan_iterations == 1
|
|
assert config.max_step_num == 3
|
|
assert config.max_search_results == 3
|
|
assert config.resources == []
|
|
assert config.mcp_settings is None
|
|
|
|
|
|
def test_from_runnable_config_with_boolean_false_values():
|
|
"""Test that boolean False values are correctly preserved and not filtered out.
|
|
|
|
This is a regression test for the bug where False values were treated as falsy
|
|
and filtered out, causing fields to revert to their default values.
|
|
"""
|
|
config_dict = {
|
|
"configurable": {
|
|
"enable_web_search": False, # Should be preserved as False, not revert to True
|
|
"enable_deep_thinking": False, # Should be preserved as False
|
|
"enforce_web_search": False, # Should be preserved as False
|
|
"enforce_researcher_search": False, # Should be preserved as False
|
|
"max_plan_iterations": 5, # Control: non-falsy value
|
|
}
|
|
}
|
|
config = Configuration.from_runnable_config(config_dict)
|
|
|
|
# Assert that False values are preserved
|
|
assert config.enable_web_search is False, "enable_web_search should be False, not default True"
|
|
assert config.enable_deep_thinking is False, "enable_deep_thinking should be False"
|
|
assert config.enforce_web_search is False, "enforce_web_search should be False"
|
|
assert config.enforce_researcher_search is False, "enforce_researcher_search should be False, not default True"
|
|
|
|
# Control: verify non-falsy values still work
|
|
assert config.max_plan_iterations == 5
|
|
|
|
|
|
def test_from_runnable_config_with_boolean_true_values():
|
|
"""Test that boolean True values work correctly (control test)."""
|
|
config_dict = {
|
|
"configurable": {
|
|
"enable_web_search": True,
|
|
"enable_deep_thinking": True,
|
|
"enforce_web_search": True,
|
|
}
|
|
}
|
|
config = Configuration.from_runnable_config(config_dict)
|
|
|
|
assert config.enable_web_search is True
|
|
assert config.enable_deep_thinking is True
|
|
assert config.enforce_web_search is True
|
|
|
|
|
|
def test_get_recursion_limit_default():
|
|
from src.config.configuration import get_recursion_limit
|
|
|
|
result = get_recursion_limit()
|
|
assert result == 25
|
|
|
|
|
|
def test_get_recursion_limit_custom_default():
|
|
from src.config.configuration import get_recursion_limit
|
|
|
|
result = get_recursion_limit(50)
|
|
assert result == 50
|
|
|
|
|
|
def test_get_recursion_limit_from_env(monkeypatch):
|
|
from src.config.configuration import get_recursion_limit
|
|
|
|
monkeypatch.setenv("AGENT_RECURSION_LIMIT", "100")
|
|
result = get_recursion_limit()
|
|
assert result == 100
|
|
|
|
|
|
def test_get_recursion_limit_invalid_env_value(monkeypatch):
|
|
from src.config.configuration import get_recursion_limit
|
|
|
|
monkeypatch.setenv("AGENT_RECURSION_LIMIT", "invalid")
|
|
result = get_recursion_limit()
|
|
assert result == 25
|
|
|
|
|
|
def test_get_recursion_limit_negative_env_value(monkeypatch):
|
|
from src.config.configuration import get_recursion_limit
|
|
|
|
monkeypatch.setenv("AGENT_RECURSION_LIMIT", "-5")
|
|
result = get_recursion_limit()
|
|
assert result == 25
|
|
|
|
|
|
def test_get_recursion_limit_zero_env_value(monkeypatch):
|
|
from src.config.configuration import get_recursion_limit
|
|
|
|
monkeypatch.setenv("AGENT_RECURSION_LIMIT", "0")
|
|
result = get_recursion_limit()
|
|
assert result == 25
|