coulomb-social/tests/test_date_backfill_operation.py
tegwick 2344b2d18b
Some checks failed
Use-case regression gate / usecase-regressions (push) Failing after 8m0s
Guard creation-date correction with full-store checks and SQL writer locks
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a18e2d-f513-7742-b8e7-12af0b744ff3
2026-10-30 22:07:31 +01:00

105 lines
4.7 KiB
Python

"""Receipt guards and full-store fingerprints use synthetic records only."""
import copy
from datetime import UTC, datetime, timedelta
import pytest
from coulomb_social.apps.spaces.date_backfill_operation import (
_content_lock,
_set_date,
execute_date_operation,
source_fingerprint,
validate_backup,
)
from coulomb_social.apps.spaces.models import Space
IMAGE = "forgejo.coulomb.social/coulomb/coulomb-social@sha256:" + "a" * 64
RECIPIENT = "age1synthetic-public-recipient"
NOW = datetime(2026, 10, 30, 12, 5, tzinfo=UTC)
def backup():
key = "platform-pg/application-archives/coulomb-social/synthetic.tar.age"
return {
"schema": "platform.application-primary-archive.v1", "application": "coulomb-social",
"status": "offsite_fetched_verified", "captured_at": "2026-10-30T12:00:00Z",
"completed_at": "2026-10-30T12:01:00Z", "image": IMAGE, "age_recipient": RECIPIENT,
"immutable_create": True, "remote_retrieval_verified": True, "version_id": "synthetic-v1",
"object_key": key, "destination": "s3://railiance-platform-pg-backup/" + key,
"encrypted_sha256": "b" * 64, "ciphertext_sha256": "b" * 64,
"database_sha256": "c" * 64, "content_sha256": "d" * 64,
"encrypted_bytes": 1234, "ciphertext_bytes": 1234,
}
@pytest.mark.parametrize("change", [
{"status": "uploaded"}, {"remote_retrieval_verified": False}, {"immutable_create": False},
{"version_id": "null"}, {"image": IMAGE + "0"}, {"age_recipient": "age1other"},
{"object_key": "platform-pg/application-archives/another/synthetic.tar.age"},
{"destination": "s3://another/synthetic"}, {"ciphertext_sha256": "e" * 64},
{"encrypted_bytes": True}, {"ciphertext_bytes": True}, {"database_sha256": "missing"},
{"captured_at": "2026-10-30T11:00:00Z"}, {"completed_at": "2026-10-31T12:00:00Z"},
{"captured_at": "2026-10-30T12:02:00Z"},
])
def test_stale_unverified_or_changed_backup_metadata_refuses(change):
receipt = {**backup(), **change}
with pytest.raises(ValueError):
validate_backup(receipt, IMAGE, RECIPIENT, now=NOW)
def test_backup_binding_is_stable_and_recovery_retains_original_even_when_old():
receipt = backup()
original = copy.deepcopy(receipt)
digest = validate_backup(receipt, IMAGE, RECIPIENT, now=NOW)
reordered = dict(reversed(list(receipt.items())))
assert validate_backup(reordered, IMAGE, RECIPIENT, now=NOW) == digest
assert receipt == original
with pytest.raises(ValueError):
validate_backup(receipt, IMAGE, RECIPIENT, now=NOW + timedelta(days=1))
assert validate_backup(receipt, IMAGE, RECIPIENT, now=NOW + timedelta(days=1),
require_fresh=False) == digest
def test_legacy_slug_collision_refuses_even_when_selected_sql_identity_is_exact():
selected = {"space_id": "selected", "tenant_id": "tenant:a", "space_slug": "same"}
snapshot = {"rows": {"spaces_space": [
{"id": "selected", "tenant_id": "tenant:a", "slug": "same", "created_at": NOW},
{"id": "another", "tenant_id": "tenant:b", "slug": "same", "created_at": NOW},
]}}
before = copy.deepcopy(snapshot)
with pytest.raises(ValueError, match="unambiguous"):
_set_date(snapshot, {"selection": selected}, "2020-01-01T00:00:00Z")
assert snapshot == before
@pytest.mark.django_db
def test_fingerprints_cover_other_tables_and_all_content_not_only_selected_pages(tmp_path):
Space.objects.create(tenant_id="tenant:synthetic", slug="synthetic")
baseline = source_fingerprint(tmp_path)
assert baseline["tables"] >= 4
(tmp_path / "arbitrary-unrelated-asset.bin").write_bytes(b"unrelated")
after_file = source_fingerprint(tmp_path)
assert after_file["tables_sha256"] == baseline["tables_sha256"]
assert after_file["files_sha256"] != baseline["files_sha256"]
Space.objects.update(title="another update")
after_sql = source_fingerprint(tmp_path)
assert after_sql["tables_sha256"] != baseline["tables_sha256"]
assert after_sql["files_sha256"] == after_file["files_sha256"]
@pytest.mark.django_db
def test_sqlite_is_observation_only_never_an_execution_backend(tmp_path):
with pytest.raises(ValueError, match="PostgreSQL execution required"):
execute_date_operation(tmp_path, {}, tmp_path / "journal.json", {}, {},
image=IMAGE, recipient=RECIPIENT)
assert not (tmp_path / "journal.json").exists()
def test_writer_lock_refuses_another_holder_and_never_creates_missing_lock(tmp_path):
with pytest.raises(FileNotFoundError), _content_lock(tmp_path):
pass
assert not list(tmp_path.iterdir())
(tmp_path / ".writer.lock").touch()
with _content_lock(tmp_path), pytest.raises(BlockingIOError), _content_lock(tmp_path):
pass