70 lines
2.5 KiB
Python
70 lines
2.5 KiB
Python
"""Agent build timing must not move work out of its original task context."""
|
|
|
|
import logging
|
|
from contextvars import ContextVar
|
|
|
|
import pytest
|
|
|
|
from deerflow.runtime.runs import worker
|
|
|
|
|
|
@pytest.mark.parametrize("supports_app_config", [False, True])
|
|
def test_build_preserves_config_and_contextvars(monkeypatch, caplog, supports_app_config):
|
|
clock = iter([10.0, 10.6])
|
|
monkeypatch.setattr(worker, "perf_counter", lambda: next(clock))
|
|
state = ContextVar("test_build_context", default="before")
|
|
config = {"configurable": {"test": True}}
|
|
app_config = object()
|
|
agent = object()
|
|
|
|
def modern_factory(*, config, app_config):
|
|
assert config is expected_config
|
|
assert app_config is expected_app_config
|
|
state.set("after")
|
|
return agent
|
|
|
|
def legacy_factory(*, config):
|
|
assert config is expected_config
|
|
state.set("after")
|
|
return agent
|
|
|
|
expected_config, expected_app_config = config, app_config
|
|
factory = modern_factory if supports_app_config else legacy_factory
|
|
with caplog.at_level(logging.DEBUG):
|
|
assert worker._build_agent_with_timing(factory, config, app_config, "test-run") is agent
|
|
assert state.get() == "after"
|
|
assert "AGENT_BUILD_TIMING run_id=test-run outcome=ok elapsed_ms=600.00" in caplog.text
|
|
assert caplog.records[-1].levelno == logging.WARNING
|
|
|
|
|
|
def test_build_failure_preserves_exception_and_does_not_log_content(monkeypatch, caplog):
|
|
clock = iter([10.0, 10.1])
|
|
monkeypatch.setattr(worker, "perf_counter", lambda: next(clock))
|
|
failure = ValueError("private prompt must not appear in timing logs")
|
|
|
|
def factory(*, config):
|
|
raise failure
|
|
|
|
with caplog.at_level(logging.DEBUG), pytest.raises(ValueError) as captured:
|
|
worker._build_agent_with_timing(factory, {}, None, "failed-run")
|
|
assert captured.value is failure
|
|
assert "outcome=error elapsed_ms=100.00" in caplog.text
|
|
assert "private prompt" not in caplog.text
|
|
assert caplog.records[-1].levelno == logging.DEBUG
|
|
|
|
|
|
def test_build_timing_handler_failure_does_not_replace_factory_error(monkeypatch):
|
|
failure = ValueError("factory failed")
|
|
|
|
def factory(*, config):
|
|
raise failure
|
|
|
|
def broken_log(*args, **kwargs):
|
|
raise RuntimeError("log handler failed")
|
|
|
|
monkeypatch.setattr(worker.logger, "debug", broken_log)
|
|
monkeypatch.setattr(worker.logger, "warning", broken_log)
|
|
with pytest.raises(ValueError) as captured:
|
|
worker._build_agent_with_timing(factory, {}, None, "failed-run")
|
|
assert captured.value is failure
|