Import AITURK IDE 1.0.0-beta.1 from Hermes 63279301; preserve MIT license
This commit is contained in:
@@ -0,0 +1,320 @@
|
||||
import shlex
|
||||
from unittest.mock import MagicMock
|
||||
|
||||
import pytest
|
||||
|
||||
import tools.file_operations as file_operations
|
||||
from tools.environments.local import LocalEnvironment
|
||||
from tools.file_operations import ExecuteResult, ShellFileOperations, _search_stdout_and_limit
|
||||
|
||||
|
||||
TIMEOUT = "[Command timed out after 60s]"
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def ops():
|
||||
env = MagicMock(cwd="/tmp/test")
|
||||
env.execute.return_value = {"output": "", "returncode": 0}
|
||||
return ShellFileOperations(env)
|
||||
|
||||
|
||||
def timeout_output(*lines: str) -> str:
|
||||
return "\n".join([*lines, TIMEOUT])
|
||||
|
||||
|
||||
def path_exists_or(output: str, returncode: int = 124):
|
||||
def execute(command, **kwargs):
|
||||
if "test -e" in command:
|
||||
return {"output": "exists", "returncode": 0}
|
||||
return {"output": output, "returncode": returncode}
|
||||
|
||||
return execute
|
||||
|
||||
|
||||
def assert_timed_out(result):
|
||||
assert result.error is None
|
||||
assert result.truncated is True
|
||||
assert result.limit_reason == "search_timeout"
|
||||
assert result.to_dict()["limit_reason"] == "search_timeout"
|
||||
|
||||
|
||||
def test_timeout_helper_strips_only_trailing_marker():
|
||||
assert _search_stdout_and_limit(ExecuteResult(timeout_output("a.py"), 124)) == ("a.py", "search_timeout")
|
||||
assert _search_stdout_and_limit(ExecuteResult("a.py\nnot a marker", 0)) == ("a.py\nnot a marker", None)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("target", "output_mode", "raw", "expected"),
|
||||
[
|
||||
("files", "content", timeout_output("src/a.py", "src/b.py"), ["src/a.py", "src/b.py"]),
|
||||
("content", "files_only", timeout_output("src/a.py", "src/b.py"), ["src/a.py", "src/b.py"]),
|
||||
("content", "content", timeout_output("src/a.py:10:foo", "src/b.py:20:foo"), ["src/a.py", "src/b.py"]),
|
||||
],
|
||||
)
|
||||
def test_rg_timeout_returns_partial_results_without_marker(ops, monkeypatch, target, output_mode, raw, expected):
|
||||
ops.env.execute.side_effect = path_exists_or(raw)
|
||||
monkeypatch.setattr(ops, "_has_command", lambda cmd: cmd == "rg")
|
||||
|
||||
result = ops.search("foo", path="/big", target=target, output_mode=output_mode)
|
||||
|
||||
assert_timed_out(result)
|
||||
if target == "content" and output_mode == "content":
|
||||
assert [match.path for match in result.matches] == expected
|
||||
assert all("timed out" not in match.content for match in result.matches)
|
||||
else:
|
||||
assert result.files == expected
|
||||
assert all("timed out" not in path for path in result.files)
|
||||
|
||||
|
||||
def test_real_rg_error_still_hard_fails(ops, monkeypatch):
|
||||
ops.env.execute.side_effect = path_exists_or("rg: regex parse error:", returncode=2)
|
||||
monkeypatch.setattr(ops, "_has_command", lambda cmd: cmd == "rg")
|
||||
|
||||
result = ops.search("[", path="/big", target="content")
|
||||
|
||||
assert result.error == "Search failed: rg: regex parse error:"
|
||||
assert result.limit_reason is None
|
||||
|
||||
|
||||
class FindRecordingEnvironment:
|
||||
is_local = False
|
||||
cwd = "/narrow"
|
||||
|
||||
def __init__(self, output="", code=0):
|
||||
self.output = output
|
||||
self.code = code
|
||||
self.commands = []
|
||||
|
||||
def execute(self, command, **kwargs):
|
||||
self.commands.append((command, kwargs))
|
||||
if command.startswith("command -v find"):
|
||||
return {"output": "yes\n", "returncode": 0}
|
||||
if command.startswith("command -v rg"):
|
||||
return {"output": "", "returncode": 1}
|
||||
if "find " in command:
|
||||
return {"output": self.output, "returncode": self.code}
|
||||
return {"output": "", "returncode": 1}
|
||||
|
||||
@property
|
||||
def find_commands(self):
|
||||
return [
|
||||
item for item in self.commands
|
||||
if item[0].startswith("find ") or "; find " in item[0]
|
||||
]
|
||||
|
||||
|
||||
class MultiRootFindEnvironment(FindRecordingEnvironment):
|
||||
def execute(self, command, **kwargs):
|
||||
self.commands.append((command, kwargs))
|
||||
if command.startswith("test -e "):
|
||||
output = "not_found\n" if "'/one/.hidden /two/.cache'" in command else "exists\n"
|
||||
return {"output": output, "returncode": 0}
|
||||
if command.startswith("command -v find"):
|
||||
return {"output": "yes\n", "returncode": 0}
|
||||
if command.startswith("command -v rg"):
|
||||
return {"output": "", "returncode": 1}
|
||||
if "find " in command:
|
||||
return {"output": self.output, "returncode": self.code}
|
||||
return {"output": "", "returncode": 1}
|
||||
|
||||
|
||||
def test_find_discovery_is_one_unsorted_pruned_bounded_scan():
|
||||
env = FindRecordingEnvironment("/narrow/a.py\n/narrow/b.py\n/narrow/c.py\n/narrow/d.py\n")
|
||||
result = ShellFileOperations(env)._search_files(
|
||||
"*.py", "/narrow", limit=2, offset=1, order="discovery"
|
||||
)
|
||||
assert result.files == ["/narrow/b.py", "/narrow/c.py"]
|
||||
assert result.truncated is True
|
||||
assert len(env.find_commands) == 1
|
||||
command, kwargs = env.find_commands[0]
|
||||
assert "-printf" not in command
|
||||
assert "sort " not in command
|
||||
assert "-prune" in command
|
||||
assert "head -n 4" in command
|
||||
assert kwargs["timeout"] <= 60
|
||||
|
||||
|
||||
def test_find_modified_is_one_exact_scan_without_bsd_retry():
|
||||
env = FindRecordingEnvironment("30 /narrow/new.py\n20 /narrow/mid.py\n10 /narrow/old.py\n")
|
||||
result = ShellFileOperations(env)._search_files(
|
||||
"*.py", "/narrow", limit=1, offset=1, order="modified"
|
||||
)
|
||||
assert result.files == ["/narrow/mid.py"]
|
||||
assert result.truncated is True
|
||||
assert len(env.find_commands) == 1
|
||||
command, _ = env.find_commands[0]
|
||||
assert "-printf '%T@ %p\\n'" in command
|
||||
assert "sort -rn" in command
|
||||
assert "head -n 3" in command
|
||||
|
||||
|
||||
def test_no_rg_multi_root_modified_is_one_globally_sorted_scan():
|
||||
env = MultiRootFindEnvironment(
|
||||
"30 /two/.cache/new.py\n10 /one/.hidden/old.py\n"
|
||||
)
|
||||
|
||||
result = ShellFileOperations(env).search(
|
||||
"*.py",
|
||||
path="/one/.hidden /two/.cache",
|
||||
target="files",
|
||||
order="modified",
|
||||
limit=1,
|
||||
)
|
||||
|
||||
assert result.error is None
|
||||
assert result.files == ["/two/.cache/new.py"]
|
||||
assert result.truncated is True
|
||||
assert len(env.find_commands) == 1
|
||||
command, kwargs = env.find_commands[0]
|
||||
assert "find '/one/.hidden' '/two/.cache'" in command
|
||||
assert "sort -rn" in command
|
||||
assert "head -n 2" in command
|
||||
assert "! -path '/one/.hidden'" in command
|
||||
assert "! -path '/two/.cache'" in command
|
||||
assert kwargs["timeout"] <= 60
|
||||
|
||||
|
||||
def test_find_dash_prefixed_relative_root_is_an_explicit_operand(
|
||||
tmp_path, monkeypatch
|
||||
):
|
||||
dash_root = tmp_path / "--version"
|
||||
ordinary_root = tmp_path / "ordinary"
|
||||
dash_root.mkdir()
|
||||
ordinary_root.mkdir()
|
||||
(dash_root / "dash.py").write_text("", encoding="utf-8")
|
||||
(ordinary_root / "plain.py").write_text("", encoding="utf-8")
|
||||
|
||||
ops = ShellFileOperations(LocalEnvironment(str(tmp_path)))
|
||||
monkeypatch.setattr(ops, "_has_command", lambda command: command == "find")
|
||||
executed = []
|
||||
real_exec = ops._exec
|
||||
|
||||
def recording_exec(command, **kwargs):
|
||||
if command.startswith("set -o pipefail; find "):
|
||||
executed.append(command)
|
||||
return real_exec(command, **kwargs)
|
||||
|
||||
monkeypatch.setattr(ops, "_exec", recording_exec)
|
||||
result = ops._search_files(
|
||||
"*.py", ["--version", "ordinary"], limit=10, offset=0
|
||||
)
|
||||
|
||||
assert result.error is None
|
||||
assert sorted(result.files) == ["./--version/dash.py", "ordinary/plain.py"]
|
||||
assert len(executed) == 1
|
||||
command_tokens = shlex.split(executed[0].removeprefix("set -o pipefail; "))
|
||||
assert "./--version" in command_tokens
|
||||
assert "--version" not in command_tokens
|
||||
assert all("find (GNU findutils)" not in path for path in result.files)
|
||||
|
||||
|
||||
def test_find_modified_capability_failure_is_actionable_without_retry():
|
||||
env = FindRecordingEnvironment("", code=1)
|
||||
result = ShellFileOperations(env)._search_files(
|
||||
"*.py", "/narrow", limit=2, offset=0, order="modified"
|
||||
)
|
||||
assert "modification-time" in (result.error or "")
|
||||
assert len(env.find_commands) == 1
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("order", "output"),
|
||||
[
|
||||
(
|
||||
"discovery",
|
||||
"/narrow/a.py\n/narrow/b.py\n/narrow/c.py\n/narrow/d.py\n",
|
||||
),
|
||||
(
|
||||
"modified",
|
||||
"40 /narrow/a.py\n30 /narrow/b.py\n20 /narrow/c.py\n10 /narrow/d.py\n",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_find_sigpipe_is_benign_only_after_fetch_limit_rows(order, output):
|
||||
result = ShellFileOperations(FindRecordingEnvironment(output, code=141))._search_files(
|
||||
"*.py", "/narrow", limit=2, offset=1, order=order
|
||||
)
|
||||
|
||||
assert result.error is None
|
||||
assert result.files == ["/narrow/b.py", "/narrow/c.py"]
|
||||
assert result.truncated is True
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("order", "output", "error_fragment"),
|
||||
[
|
||||
("discovery", "/narrow/partial.py\n", "bounded find traversal"),
|
||||
("modified", "10 /narrow/partial.py\n", "modification-time"),
|
||||
],
|
||||
)
|
||||
def test_find_sigpipe_with_fewer_than_fetch_limit_rows_fails_closed(
|
||||
order, output, error_fragment
|
||||
):
|
||||
result = ShellFileOperations(FindRecordingEnvironment(output, code=141))._search_files(
|
||||
"*.py", "/narrow", limit=2, offset=1, order=order
|
||||
)
|
||||
|
||||
assert error_fragment in (result.error or "")
|
||||
assert result.files == []
|
||||
assert result.total_count == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("order", "output", "error_fragment"),
|
||||
[
|
||||
("discovery", "/narrow/partial.py\n", "bounded find traversal"),
|
||||
("modified", "/narrow/not-a-timestamp.py\n", "modification-time"),
|
||||
],
|
||||
)
|
||||
def test_find_hard_error_discards_partial_output(order, output, error_fragment):
|
||||
env = FindRecordingEnvironment(output, code=2)
|
||||
|
||||
result = ShellFileOperations(env)._search_files(
|
||||
"*.py", "/narrow", limit=2, offset=0, order=order
|
||||
)
|
||||
|
||||
assert error_fragment in (result.error or "")
|
||||
assert result.files == []
|
||||
assert result.total_count == 0
|
||||
|
||||
|
||||
def test_find_timeout_preserves_partial_results_and_limit_reason():
|
||||
env = FindRecordingEnvironment(timeout_output("/narrow/partial.py"), code=124)
|
||||
|
||||
result = ShellFileOperations(env)._search_files(
|
||||
"*.py", "/narrow", limit=2, offset=0, order="discovery"
|
||||
)
|
||||
|
||||
assert result.files == ["/narrow/partial.py"]
|
||||
assert_timed_out(result)
|
||||
|
||||
|
||||
def test_find_zero_match_exit_zero_is_success():
|
||||
result = ShellFileOperations(FindRecordingEnvironment("", code=0))._search_files(
|
||||
"*.missing", "/narrow", limit=2, offset=0, order="discovery"
|
||||
)
|
||||
|
||||
assert result.error is None
|
||||
assert result.files == []
|
||||
|
||||
|
||||
def test_local_broad_no_rg_refuses_before_find(monkeypatch, tmp_path):
|
||||
home = tmp_path / "home"
|
||||
home.mkdir()
|
||||
ops = ShellFileOperations(LocalEnvironment(str(home)))
|
||||
monkeypatch.setattr(file_operations, "_HOME", str(home))
|
||||
monkeypatch.setattr(file_operations.os.path, "isfile", lambda path: False)
|
||||
commands = []
|
||||
|
||||
def fake_exec(command, **kwargs):
|
||||
commands.append((command, kwargs))
|
||||
if command.startswith("command -v rg"):
|
||||
return ExecuteResult("", 1)
|
||||
if command.startswith("command -v find"):
|
||||
return ExecuteResult("yes\n", 0)
|
||||
raise AssertionError(f"broad fallback must not execute: {command}")
|
||||
|
||||
monkeypatch.setattr(ops, "_exec", fake_exec)
|
||||
result = ops._search_files("*.py", str(home), 10, 0, "discovery")
|
||||
assert "ripgrep" in (result.error or "").lower()
|
||||
assert not any(command.startswith("find ") for command, _ in commands)
|
||||
Reference in New Issue
Block a user