- Move agent code from backend/src/agent/ to agent/src/ss_tools/agent/ - Extract shared stdlib-only utilities to shared/src/ss_tools/shared/ - Add #region/#endregion contracts to all ~140 functions (INV_1 compliance) - Update docker files, entrypoint, build scripts for new package layout - Backend now imports ss_tools.shared._llm_health (no gradio/langchain deps) - Add specs for 036-039 feature plans
88 lines
3.7 KiB
Python
88 lines
3.7 KiB
Python
# #region Test.AgentChat.ToolTimeout [C:3] [TYPE Module] [SEMANTICS test,agent,tools,timeout]
|
|
# @BRIEF Contract tests for _execute_with_timeout — configurable timeout wrapper.
|
|
# @RELATION BINDS_TO -> [AgentChat.Tools.Timeout]
|
|
# @TEST_EDGE: complete_under_timeout -> Tool completes normally, returns result
|
|
# @TEST_EDGE: read_tool_timeout -> Read tool exceeds timeout, raises TimeoutError
|
|
# @TEST_EDGE: write_tool_timeout -> Write tool exceeds timeout, raises TimeoutError
|
|
|
|
import asyncio
|
|
from unittest.mock import AsyncMock, patch
|
|
|
|
import pytest
|
|
|
|
|
|
# ── Tests ───────────────────────────────────────────────────────────
|
|
|
|
|
|
# #region test_completes_under_timeout [C:2] [TYPE Function]
|
|
# @BRIEF GIVEN a tool that returns quickly WHEN _execute_with_timeout is called with a 30s timeout THEN the result is returned normally.
|
|
@pytest.mark.asyncio
|
|
async def test_completes_under_timeout():
|
|
"""Tool returns its result before the timeout expires."""
|
|
from ss_tools.agent.tools import _execute_with_timeout
|
|
|
|
expected = {"status": "ok", "data": [1, 2, 3]}
|
|
fast_fn = AsyncMock(return_value=expected)
|
|
|
|
with patch("ss_tools.agent.tools.logger.explore") as mock_explore:
|
|
result = await _execute_with_timeout("fast_tool", fast_fn, is_write=False, timeout_s=30)
|
|
|
|
assert result == expected
|
|
fast_fn.assert_called_once()
|
|
mock_explore.assert_not_called()
|
|
# #endregion test_completes_under_timeout
|
|
|
|
|
|
# #region test_read_tool_timeout [C:2] [TYPE Function]
|
|
# @BRIEF GIVEN a read tool that exceeds the timeout WHEN _execute_with_timeout is called THEN TimeoutError is raised and logger.explore is invoked.
|
|
@pytest.mark.asyncio
|
|
async def test_read_tool_timeout():
|
|
"""Read tool that sleeps longer than timeout_s must raise TimeoutError."""
|
|
from ss_tools.agent.tools import _execute_with_timeout
|
|
|
|
async def slow_read():
|
|
await asyncio.sleep(0.3)
|
|
return "never_reached"
|
|
|
|
with patch("ss_tools.agent.tools.logger.explore") as mock_explore:
|
|
with pytest.raises(TimeoutError):
|
|
await _execute_with_timeout("slow_read", slow_read, is_write=False, timeout_s=0.05)
|
|
|
|
mock_explore.assert_called_once()
|
|
call_args = mock_explore.call_args
|
|
assert call_args[0][0] == "Tool timeout"
|
|
payload = call_args[1]["payload"]
|
|
assert payload["tool"] == "slow_read"
|
|
assert payload["timeout_s"] == 0.05
|
|
assert payload["is_write"] is False
|
|
assert call_args[1]["extra"]["src"] == "AgentChat.Tools.Timeout"
|
|
# #endregion test_read_tool_timeout
|
|
|
|
|
|
# #region test_write_tool_timeout [C:2] [TYPE Function]
|
|
# @BRIEF GIVEN a write tool that exceeds the timeout WHEN _execute_with_timeout is called THEN TimeoutError is raised with is_write=True logged.
|
|
@pytest.mark.asyncio
|
|
async def test_write_tool_timeout():
|
|
"""Write tool that sleeps longer than timeout_s must raise TimeoutError."""
|
|
from ss_tools.agent.tools import _execute_with_timeout
|
|
|
|
async def slow_write():
|
|
await asyncio.sleep(0.3)
|
|
return "never_reached"
|
|
|
|
with patch("ss_tools.agent.tools.logger.explore") as mock_explore:
|
|
with pytest.raises(TimeoutError):
|
|
await _execute_with_timeout("slow_write", slow_write, is_write=True, timeout_s=0.05)
|
|
|
|
mock_explore.assert_called_once()
|
|
call_args = mock_explore.call_args
|
|
assert call_args[0][0] == "Tool timeout"
|
|
payload = call_args[1]["payload"]
|
|
assert payload["tool"] == "slow_write"
|
|
assert payload["timeout_s"] == 0.05
|
|
assert payload["is_write"] is True
|
|
assert call_args[1]["extra"]["src"] == "AgentChat.Tools.Timeout"
|
|
# #endregion test_write_tool_timeout
|
|
|
|
# #endregion Test.AgentChat.ToolTimeout
|