deerflow2/backend/tests/test_aio_sandbox_local_back...

118 lines
4.0 KiB
Python

from unittest.mock import MagicMock
from deerflow.community.aio_sandbox.local_backend import LocalContainerBackend, _format_container_mount
def test_format_container_mount_uses_mount_syntax_for_docker_windows_paths():
args = _format_container_mount("docker", "D:/deer-flow/backend/.deer-flow/threads", "/mnt/threads", False)
assert args == [
"--mount",
"type=bind,src=D:/deer-flow/backend/.deer-flow/threads,dst=/mnt/threads",
]
def test_format_container_mount_marks_docker_readonly_mounts():
args = _format_container_mount("docker", "/host/path", "/mnt/path", True)
assert args == [
"--mount",
"type=bind,src=/host/path,dst=/mnt/path,readonly",
]
def test_format_container_mount_keeps_volume_syntax_for_apple_container():
args = _format_container_mount("container", "/host/path", "/mnt/path", True)
assert args == [
"-v",
"/host/path:/mnt/path:ro",
]
# ── extra_env injection ──────────────────────────────────────────────────────
def _make_backend(runtime: str = "docker") -> LocalContainerBackend:
"""Build a minimal LocalContainerBackend without real config."""
backend = LocalContainerBackend.__new__(LocalContainerBackend)
backend._runtime = runtime
backend._container_prefix = "test"
backend._environment = {}
backend._config_mounts = []
backend._base_port = 9000
backend._image = "test-image:latest"
return backend
def test_start_container_injects_extra_env(monkeypatch):
"""_start_container must append -e KEY=VALUE for each extra_env entry."""
backend = _make_backend()
captured: list[list[str]] = []
def fake_run(cmd, **_kwargs):
captured.append(list(cmd))
result = MagicMock()
result.returncode = 0
result.stdout = "fake-container-id\n"
return result
monkeypatch.setattr("deerflow.community.aio_sandbox.local_backend.subprocess.run", fake_run)
backend._start_container("c", 9000, extra_env={"THREAD_ID": "thread-abc", "FOO": "bar"})
cmd = captured[0]
assert "-e" in cmd
env_pairs = {cmd[i + 1] for i in range(len(cmd)) if cmd[i] == "-e"}
assert "THREAD_ID=thread-abc" in env_pairs
assert "FOO=bar" in env_pairs
def test_start_container_no_extra_env_does_not_inject(monkeypatch):
"""_start_container with no extra_env must not add unexpected -e flags."""
backend = _make_backend()
captured: list[list[str]] = []
def fake_run(cmd, **_kwargs):
captured.append(list(cmd))
result = MagicMock()
result.returncode = 0
result.stdout = "fake-container-id\n"
return result
monkeypatch.setattr("deerflow.community.aio_sandbox.local_backend.subprocess.run", fake_run)
backend._start_container("c", 9000)
cmd = captured[0]
env_pairs = {cmd[i + 1] for i in range(len(cmd)) if cmd[i] == "-e"}
assert all("THREAD_ID" not in pair for pair in env_pairs)
def test_start_container_extra_env_overrides_static_env(monkeypatch):
"""Runtime extra_env values must appear after static env, effectively overriding same-key entries."""
backend = _make_backend()
backend._environment = {"MY_VAR": "static"}
captured: list[list[str]] = []
def fake_run(cmd, **_kwargs):
captured.append(list(cmd))
result = MagicMock()
result.returncode = 0
result.stdout = "fake-container-id\n"
return result
monkeypatch.setattr("deerflow.community.aio_sandbox.local_backend.subprocess.run", fake_run)
backend._start_container("c", 9000, extra_env={"MY_VAR": "runtime"})
cmd = captured[0]
env_pairs = [cmd[i + 1] for i in range(len(cmd)) if cmd[i] == "-e"]
# Both entries should be present; the runtime one comes after, which Docker respects
assert "MY_VAR=static" in env_pairs
assert "MY_VAR=runtime" in env_pairs
assert env_pairs.index("MY_VAR=runtime") > env_pairs.index("MY_VAR=static")