coulomb-social/tests/test_restore_recovery.py
tegwick b897aa1ee6
Some checks failed
Use-case regression gate / usecase-regressions (push) Has been cancelled
feat: prepare isolated recovery and guarded fresh ReichelAg capture
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a10e2d-a5ef-7e92-b03d-b1694e915680
2026-10-06 22:11:42 +02:00

41 lines
1.5 KiB
Python

"""Logical backup comparisons must catch changed rows, sequences and paths."""
import importlib.util
import io
import tarfile
from pathlib import Path
import pytest
@pytest.fixture
def helper():
path = Path(__file__).resolve().parents[1] / 'scripts/restore-paired-snapshot.py'
spec = importlib.util.spec_from_file_location('csoc_restore', path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
def test_data_comparison_ignores_order_but_detects_changes(helper):
a = b'COPY public.demo (id, value) FROM stdin;\n1\tone\n2\ttwo\n\\.\n'
b = b'-- SQL header\nCOPY public.demo (id, value) FROM stdin;\n2\ttwo\n1\tone\n\\.\n'
assert helper.data_fingerprint(a) == helper.data_fingerprint(b)
assert helper.data_fingerprint(a) != helper.data_fingerprint(b.replace(b'two', b'changed'))
assert helper.data_fingerprint(a) != helper.data_fingerprint(
a + b"SELECT pg_catalog.setval('public.demo_seq', 9, true);\n")
def test_partial_copy_is_rejected(helper):
with pytest.raises(helper.Refused):
helper.data_fingerprint(b'COPY public.demo (id) FROM stdin;\n1\n')
def test_content_archive_rejects_escape(helper, tmp_path):
archive = tmp_path / 'bad.tar.gz'
with tarfile.open(archive, 'w:gz') as t:
info = tarfile.TarInfo('content/../../outside')
info.size = 4
t.addfile(info, io.BytesIO(b'data'))
with pytest.raises(helper.Refused):
helper.content_fingerprint(archive, tmp_path / 'restored')
assert not (tmp_path / 'outside').exists()