Files
openswarm/backend/tests/test_app_export_no_stale_files.py

73 lines
2.6 KiB
Python

"""Export must not carry the stale inline output.files snapshot when a workspace
exists. output.files is frozen at creation (v1); the agent edits land on disk
(v2). serialize() used to ship the v1 snapshot alongside the v2 disk copy, so an
imported app reverted every edited file (new files survived since they were never
in the snapshot). With a workspace, disk is the single source of truth; only true
flat apps (no workspace) still carry the inline copy."""
import uuid
import pytest
from backend.apps.outputs import workspace_io
from backend.apps.outputs.models import Output
from backend.apps.swarm.entities import apps as apps_mod
from backend.apps.swarm.entities.apps import AppExportable
class P_Ctx:
pass
@pytest.fixture
def p_ws_root(tmp_path, monkeypatch):
root = tmp_path / "ws"
root.mkdir()
out = tmp_path / "out"
out.mkdir()
monkeypatch.setattr(apps_mod, "OUTPUTS_WORKSPACE_DIR", str(root))
monkeypatch.setattr(workspace_io, "DATA_DIR", str(out))
return root
def p_make_app(ws_root, *, workspace: bool) -> str:
wsid = uuid.uuid4().hex if workspace else None
if wsid:
folder = ws_root / wsid
folder.mkdir()
(folder / "app.py").write_text("print('v1')\n")
o = Output(
name="Demo", description="", icon="view_quilt",
input_schema={"type": "object", "properties": {}, "required": []},
files={"app.py": "print('v1')\n"},
workspace_id=wsid, session_id=None,
)
workspace_io.save(o)
return o.id
def test_workspace_app_export_omits_stale_inline_files(p_ws_root):
oid = p_make_app(p_ws_root, workspace=True)
o = workspace_io.load_output(oid)
folder = p_ws_root / o.workspace_id
# agent edit -> v2 on disk: modify app.py + add new.py (output.files stays v1)
(folder / "app.py").write_text("print('v2 EDITED')\n")
(folder / "new.py").write_text("print('v2 NEW')\n")
exp = AppExportable.load(oid)
payload = exp.serialize(P_Ctx())
disk = exp.files()
# the stale v1 snapshot must NOT ride along
assert payload["files"] == {}, "workspace app must not export the frozen output.files snapshot"
# disk (v2) is what travels, both the edit and the new file
assert disk["workspace/app.py"] == b"print('v2 EDITED')\n"
assert disk["workspace/new.py"] == b"print('v2 NEW')\n"
def test_flat_app_without_workspace_still_carries_inline_files(p_ws_root):
oid = p_make_app(p_ws_root, workspace=False)
exp = AppExportable.load(oid)
payload = exp.serialize(P_Ctx())
# no workspace -> inline files ARE the source, must survive export
assert payload["files"] == {"app.py": "print('v1')\n"}