"""Unit tests for code_exec tool."""
import pytest
from navi.tools.code_exec import CodeExecTool
class TestCodeExecTool:
@pytest.fixture
def tool(self):
return CodeExecTool()
async def test_hello_world(self, tool):
result = await tool.execute({"code": "print('hello')"})
assert result.success
assert "hello" in result.output
async def test_math(self, tool):
result = await tool.execute({"code": "print(2 + 3)"})
assert result.success
assert "5" in result.output
async def test_stderr(self, tool):
result = await tool.execute({"code": "import sys; print('err', file=sys.stderr)"})
# stderr is captured but the tool may or may not consider it an error
assert "err" in (result.output or result.error or "")
async def test_syntax_error(self, tool):
result = await tool.execute({"code": "print("})
assert not result.success
async def test_metadata_carries_returncode_and_language(self, tool):
result = await tool.execute({"code": "print('hi')"})
assert result.success
assert result.metadata["returncode"] == 0
assert result.metadata["language"] == "python"
async def test_timeout_param_clamped_to_max(self, tool):
# 99999 -> clamped to _MAX_TIMEOUT (300). Fast code still succeeds; we
# only assert the clamp path doesn't error and metadata is well-formed.
result = await tool.execute({"code": "print('ok')", "timeout": 99999})
assert result.success
assert result.metadata["language"] == "python"
async def test_timeout_param_triggers_timeout(self, tool):
result = await tool.execute({"code": "import time; time.sleep(5)", "timeout": 1})
assert not result.success
assert result.error == "timeout"
assert "timed out after 1s" in result.output
assert result.metadata["language"] == "python"
assert result.metadata["timeout"] == 1