"""Tests for the read_many_files tool.""" from pathlib import Path import pytest from app.models.config import AppConfig, load_config from app.models.tool_call import ToolResultStatus from app.tools.filesystem import ReadManyFilesTool @pytest.fixture def config() -> AppConfig: return load_config() @pytest.fixture def tmp_workspace(tmp_path: Path, config: AppConfig) -> tuple[Path, AppConfig]: """Create a temporary workspace for read_many_files tests.""" config.agent.workspace_root = tmp_path return tmp_path, config class TestReadManyFilesTool: def test_read_multiple_files(self, tmp_workspace: tuple[Path, AppConfig]) -> None: ws, cfg = tmp_workspace (ws / "a.txt").write_text("alpha") (ws / "b.txt").write_text("bravo") tool = ReadManyFilesTool(ws, cfg) result = tool.run("tc-1", {"file_paths": ["a.txt", "b.txt"]}) assert result.status == ToolResultStatus.SUCCESS assert "=== a.txt ===" in result.output assert "alpha" in result.output assert "=== b.txt ===" in result.output assert "bravo" in result.output def test_partial_failure(self, tmp_workspace: tuple[Path, AppConfig]) -> None: ws, cfg = tmp_workspace (ws / "exists.txt").write_text("hello") tool = ReadManyFilesTool(ws, cfg) result = tool.run("tc-2", {"file_paths": ["exists.txt", "missing.txt"]}) assert result.status == ToolResultStatus.SUCCESS assert "hello" in result.output assert "[ERROR]" in result.output assert "=== missing.txt ===" in result.output def test_all_files_fail(self, tmp_workspace: tuple[Path, AppConfig]) -> None: ws, cfg = tmp_workspace tool = ReadManyFilesTool(ws, cfg) result = tool.run("tc-3", {"file_paths": ["no1.txt", "no2.txt"]}) assert result.status == ToolResultStatus.ERROR assert "All files failed" in (result.error or "") def test_empty_file_paths(self, tmp_workspace: tuple[Path, AppConfig]) -> None: ws, cfg = tmp_workspace tool = ReadManyFilesTool(ws, cfg) result = tool.run("tc-4", {"file_paths": []}) assert result.status == ToolResultStatus.ERROR assert "empty" in (result.error or "").lower() def test_path_security_inline_error(self, tmp_workspace: tuple[Path, AppConfig]) -> None: ws, cfg = tmp_workspace (ws / "safe.txt").write_text("ok") tool = ReadManyFilesTool(ws, cfg) result = tool.run("tc-5", {"file_paths": ["safe.txt", "../../etc/passwd"]}) assert result.status == ToolResultStatus.SUCCESS assert "ok" in result.output assert "[ERROR]" in result.output assert "outside" in result.output.lower()