Files
SeedPass/src/tests/test_document_file_io.py
T

156 lines
5.3 KiB
Python

from pathlib import Path
from tempfile import TemporaryDirectory
import hashlib
import pytest
from helpers import TEST_PASSWORD, TEST_SEED, create_vault
from seedpass.core.backup import BackupManager
from seedpass.core.config_manager import ConfigManager
from seedpass.core.entry_management import EntryManager
from seedpass.core.portable_backup import export_backup, import_backup
pytestmark = pytest.mark.determinism
def _make_entry_manager(tmp_path: Path) -> EntryManager:
vault, _ = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
return EntryManager(vault, backup_mgr)
def _make_managers(tmp_path: Path) -> tuple[EntryManager, BackupManager]:
vault, _ = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
cfg_mgr = ConfigManager(vault, tmp_path)
backup_mgr = BackupManager(tmp_path, cfg_mgr)
return EntryManager(vault, backup_mgr), backup_mgr
def _deterministic_text_bytes(size: int) -> str:
"""Return deterministic ASCII text of at least *size* bytes."""
block = (
"SeedPass deterministic document payload block. "
"0123456789 abcdefghijklmnopqrstuvwxyz\n"
)
repeats = (size // len(block)) + 1
text = block * repeats
return text[:size]
def test_import_document_file_roundtrip():
with TemporaryDirectory() as tmpdir:
base = Path(tmpdir)
entry_mgr = _make_entry_manager(base)
source = base / "notes.md"
source.write_text("# hello\nworld\n", encoding="utf-8")
idx = entry_mgr.import_document_file(source, notes="imported", tags=["docs"])
entry = entry_mgr.retrieve_entry(idx)
assert entry is not None
assert entry["kind"] == "document"
assert entry["label"] == "notes"
assert entry["file_type"] == "md"
assert entry["content"] == "# hello\nworld\n"
assert entry["notes"] == "imported"
assert entry["tags"] == ["docs"]
def test_export_document_file_writes_expected_content():
with TemporaryDirectory() as tmpdir:
base = Path(tmpdir)
entry_mgr = _make_entry_manager(base)
idx = entry_mgr.add_document("Runbook", "line1\nline2", file_type="txt")
out_dir = base / "exports"
dest = entry_mgr.export_document_file(idx, output_path=out_dir)
assert dest.exists()
assert dest.suffix == ".txt"
assert dest.read_text(encoding="utf-8") == "line1\nline2"
@pytest.mark.parametrize("size_bytes", [1024, 512 * 1024, 1024 * 1024])
def test_import_export_large_document_roundtrip_is_byte_stable(size_bytes: int):
with TemporaryDirectory() as tmpdir:
base = Path(tmpdir)
entry_mgr = _make_entry_manager(base)
content = _deterministic_text_bytes(size_bytes)
source = base / "large_doc.md"
source.write_text(content, encoding="utf-8")
idx = entry_mgr.import_document_file(source, tags=["large", "determinism"])
entry = entry_mgr.retrieve_entry(idx)
assert entry is not None
assert entry["file_type"] == "md"
assert entry["content"] == content
out_dir = base / "out"
exported = entry_mgr.export_document_file(idx, output_path=out_dir)
exported_content = exported.read_text(encoding="utf-8")
assert exported_content == content
assert (
hashlib.sha256(exported_content.encode("utf-8")).hexdigest()
== hashlib.sha256(content.encode("utf-8")).hexdigest()
)
@pytest.mark.parametrize("encrypt", [True, False], ids=["encrypted", "plaintext"])
def test_portable_backup_restore_preserves_document_content_and_extension(
encrypt: bool,
):
with TemporaryDirectory() as tmpdir:
base = Path(tmpdir)
entry_mgr, backup_mgr = _make_managers(base)
content = _deterministic_text_bytes(256 * 1024)
idx = entry_mgr.add_document(
"Ops Runbook",
content,
file_type="py",
notes="critical",
tags=["ops", "runbook"],
)
before = entry_mgr.retrieve_entry(idx)
assert before is not None
export_path = base / "portable_export.json"
export_backup(
entry_mgr.vault,
backup_mgr,
export_path,
parent_seed=TEST_SEED,
encrypt=encrypt,
)
entry_mgr.modify_entry(
idx,
label="mutated",
content="mutated content",
file_type="txt",
notes="changed",
tags=["changed"],
)
import_backup(
entry_mgr.vault,
backup_mgr,
export_path,
parent_seed=TEST_SEED,
)
entry_mgr.clear_cache()
after = entry_mgr.retrieve_entry(idx)
assert after == before
def test_backup_manager_restore_latest_preserves_large_document_content():
with TemporaryDirectory() as tmpdir:
base = Path(tmpdir)
entry_mgr, backup_mgr = _make_managers(base)
content = _deterministic_text_bytes(300 * 1024)
idx = entry_mgr.add_document("Design Doc", content, file_type="txt")
before = entry_mgr.retrieve_entry(idx)
assert before is not None
backup_mgr.restore_latest_backup()
restored = entry_mgr.retrieve_entry(idx)
assert restored == before