import logging import os from types import SimpleNamespace from deerflow.community.aio_sandbox.local_backend import LocalContainerBackend, _format_container_command_for_log, _format_container_mount, _redact_container_command_for_log 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", ] def test_redact_container_command_for_log_redacts_env_values(): redacted = _redact_container_command_for_log( [ "docker", "run", "-e", "API_KEY=secret-value", "--env=TOKEN=token-value", "--name", "sandbox", "image", ] ) assert "API_KEY=" in redacted assert "--env=TOKEN=" in redacted assert "secret-value" not in " ".join(redacted) assert "token-value" not in " ".join(redacted) def test_redact_container_command_for_log_keeps_inherited_env_names(): redacted = _redact_container_command_for_log( [ "docker", "run", "-e", "API_KEY", "--env=TOKEN", "--name", "sandbox", "image", ] ) assert redacted == [ "docker", "run", "-e", "API_KEY", "--env=TOKEN", "--name", "sandbox", "image", ] def test_format_container_command_for_log_uses_windows_quoting(monkeypatch): monkeypatch.setattr(os, "name", "nt") command = _format_container_command_for_log(["docker", "run", "--name", "sandbox one", "image"]) assert command == 'docker run --name "sandbox one" image' def test_start_container_logs_redacted_env_values(monkeypatch, caplog): backend = LocalContainerBackend( image="sandbox:latest", base_port=8080, container_prefix="sandbox", config_mounts=[], environment={"API_KEY": "secret-value", "NORMAL": "visible-value"}, ) monkeypatch.setattr(backend, "_runtime", "docker") captured_cmd: list[str] = [] def fake_run(cmd, **kwargs): captured_cmd.extend(cmd) return SimpleNamespace(stdout="container-id\n", stderr="", returncode=0) monkeypatch.setattr("subprocess.run", fake_run) with caplog.at_level(logging.INFO, logger="deerflow.community.aio_sandbox.local_backend"): backend._start_container("sandbox-test", 18080) joined_cmd = " ".join(captured_cmd) assert "API_KEY=secret-value" in joined_cmd assert "NORMAL=visible-value" in joined_cmd log_output = "\n".join(record.getMessage() for record in caplog.records) assert "API_KEY=" in log_output assert "NORMAL=" in log_output assert "secret-value" not in log_output assert "visible-value" not in log_output