mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-11-08 11:40:35 +00:00
* feat(extensions): add versioned team file handoffs * fix(extensions): fence team artifact execution and snapshots * fix(agent-teams): retain resumed keys and bound artifact transfers * ci: reclaim runner space before sandbox image smoke * ci: budget sandbox image preparation separately * fix(extensions): version artifact contracts and document snapshots
112 lines
3.9 KiB
Python
112 lines
3.9 KiB
Python
"""Execute the remote snapshot protocol against real POSIX files, offline."""
|
|
|
|
import os
|
|
import subprocess
|
|
import sys
|
|
from types import SimpleNamespace
|
|
|
|
import pytest
|
|
from deerflow_extension_api import AgentRunError
|
|
|
|
from app.gateway.extension_artifacts import MAX_BYTES
|
|
|
|
pytestmark = pytest.mark.skipif(os.name != "posix", reason="Descriptor-confined snapshots require POSIX")
|
|
|
|
|
|
@pytest.fixture
|
|
def remote(tmp_path):
|
|
root = tmp_path / "remote"
|
|
root.mkdir()
|
|
|
|
def command(script, **kwargs):
|
|
# The transport is replaced, not the script executed in the sandbox.
|
|
result = subprocess.run(script.replace("python3 ", sys.executable + " ", 1), shell=True, capture_output=True, text=True, timeout=10)
|
|
assert result.returncode == 0, result.stderr
|
|
return result.stdout
|
|
|
|
return SimpleNamespace(artifact_root=str(root), execute_command=command)
|
|
|
|
|
|
@pytest.mark.parametrize("replacement", ["edit", "symlink", "directory", "hardlink"])
|
|
def test_remote_publication_reuses_exact_bytes_and_preserves_changed_destinations(remote, tmp_path, replacement):
|
|
from deerflow.sandbox.artifact_snapshot import publish_snapshot
|
|
|
|
content = b"\x00\xff" * 40000
|
|
name = 'report-"文件.bin'
|
|
publish_snapshot(remote, name, content)
|
|
publish_snapshot(remote, name, content)
|
|
target = tmp_path / "remote/uploads" / name
|
|
assert target.read_bytes() == content
|
|
unrelated = tmp_path / "unrelated"
|
|
unrelated.write_bytes(b"private")
|
|
target.unlink()
|
|
if replacement == "edit":
|
|
target.write_bytes(b"recipient edit")
|
|
elif replacement == "symlink":
|
|
target.symlink_to(unrelated)
|
|
elif replacement == "directory":
|
|
target.mkdir()
|
|
else:
|
|
import os
|
|
|
|
os.link(unrelated, target)
|
|
with pytest.raises(AgentRunError):
|
|
publish_snapshot(remote, name, content)
|
|
assert unrelated.read_bytes() == b"private"
|
|
if replacement == "edit":
|
|
assert target.read_bytes() == b"recipient edit"
|
|
assert not list(target.parent.glob(".artifact-*.part"))
|
|
|
|
|
|
def test_remote_snapshots_reject_parent_symlinks(remote, tmp_path):
|
|
from deerflow.sandbox.artifact_snapshot import publish_snapshot, read_snapshot
|
|
|
|
outside = tmp_path / "outside"
|
|
outside.mkdir()
|
|
(outside / "report.txt").write_bytes(b"private")
|
|
(tmp_path / "remote/uploads").symlink_to(outside, target_is_directory=True)
|
|
(tmp_path / "remote/outputs").symlink_to(outside, target_is_directory=True)
|
|
with pytest.raises(AgentRunError):
|
|
publish_snapshot(remote, "report.txt", b"replacement")
|
|
with pytest.raises(AgentRunError):
|
|
read_snapshot(remote, "report.txt")
|
|
assert (outside / "report.txt").read_bytes() == b"private"
|
|
|
|
|
|
@pytest.mark.parametrize("size", [0, 40000, MAX_BYTES, MAX_BYTES + 1])
|
|
def test_remote_capture_reads_exact_bounded_binary_bytes(remote, tmp_path, size):
|
|
from deerflow.sandbox.artifact_snapshot import read_snapshot
|
|
|
|
outputs = tmp_path / "remote/outputs"
|
|
outputs.mkdir()
|
|
content = bytes(range(256)) * (size // 256) + b"x" * (size % 256)
|
|
(outputs / "report.bin").write_bytes(content)
|
|
if size > MAX_BYTES:
|
|
with pytest.raises(AgentRunError):
|
|
read_snapshot(remote, "report.bin")
|
|
else:
|
|
assert read_snapshot(remote, "report.bin") == content
|
|
|
|
|
|
def test_remote_capture_rejects_replacement_between_chunks(remote, tmp_path):
|
|
from deerflow.sandbox.artifact_snapshot import read_snapshot
|
|
|
|
outputs = tmp_path / "remote/outputs"
|
|
outputs.mkdir()
|
|
target = outputs / "report.txt"
|
|
target.write_bytes(b"a" * 100000)
|
|
original = remote.execute_command
|
|
count = 0
|
|
|
|
def command(script, **kwargs):
|
|
nonlocal count
|
|
result = original(script, **kwargs)
|
|
count += 1
|
|
if count == 1:
|
|
target.write_bytes(b"b" * 100000)
|
|
return result
|
|
|
|
remote.execute_command = command
|
|
with pytest.raises(AgentRunError):
|
|
read_snapshot(remote, "report.txt")
|