From 6e844d21b34c6aa2ee282253d3acf42037946af1 Mon Sep 17 00:00:00 2001 From: Maxwell Date: Fri, 2 Oct 2026 11:44:18 +0100 Subject: [PATCH] test: lock atomic evidence replacement Show that evidence writes create parents, replace the destination completely, and still publish when fsync fails. Co-authored-by: Cursor --- tests/test_file_safety.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 tests/test_file_safety.py diff --git a/tests/test_file_safety.py b/tests/test_file_safety.py new file mode 100644 index 0000000..19a9d0b --- /dev/null +++ b/tests/test_file_safety.py @@ -0,0 +1,30 @@ +from __future__ import annotations + +from pathlib import Path + +from headerproof.file_safety import atomic_write_text + + +def test_atomic_write_text_creates_parents_and_replaces_destination(tmp_path: Path) -> None: + destination = tmp_path / "nested" / "evidence" / "metadata.json" + + atomic_write_text(destination, "first\n") + atomic_write_text(destination, "second complete\n") + + assert destination.read_text(encoding="utf-8") == "second complete\n" + assert list(destination.parent.glob("*.tmp")) == [] + + +def test_atomic_write_text_tolerates_fsync_oserror(tmp_path: Path, monkeypatch) -> None: + destination = tmp_path / "summary.md" + destination.write_text("previous\n", encoding="utf-8") + + def fail_fsync(_fd: int) -> None: + raise OSError("fsync unavailable") + + monkeypatch.setattr("headerproof.file_safety.os.fsync", fail_fsync) + + atomic_write_text(destination, "replaced\n") + + assert destination.read_text(encoding="utf-8") == "replaced\n" + assert not (tmp_path / "summary.md.tmp").exists()