mirror of
https://github.com/kevinveenbirkenbach/docker-volume-backup.git
synced 2026-11-06 02:57:59 +00:00
Dumps stream through gzip into <db>.backup.sql.gz; no uncompressed copy touches the disk. Restore reads gzip and plain dumps by their magic bytes, verifies a gzip dump to its end before anything is dropped, and still finds the uncompressed names of older generations. The manifest names the compression. 🎯 Fix: 92 % 💥 Break: 20 % 💸 Cost: – ⏱️ Time: – 🛡️ Security: ~100 % 🏆 Score: 74 🚦 Gate: ⛔ break 20 % > 5 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
78 lines
2.6 KiB
Python
78 lines
2.6 KiB
Python
"""Contract of the generation manifest document and the file it lands in."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
import tempfile
|
|
import unittest
|
|
from pathlib import Path
|
|
|
|
from baudolo.backup.dumps import VolumeOutcome
|
|
from baudolo.backup.layout import write_manifest
|
|
from baudolo.generation import (
|
|
CLUSTER_SUFFIX,
|
|
DUMP_SUFFIX,
|
|
FILES_DIR,
|
|
LEGACY_CLUSTER_SUFFIX,
|
|
LEGACY_DUMP_SUFFIX,
|
|
MANIFEST_FILE,
|
|
MANIFEST_SCHEMA,
|
|
SQL_DIR,
|
|
manifest_document,
|
|
)
|
|
|
|
|
|
class TestManifestDocument(unittest.TestCase):
|
|
def test_it_states_the_layout_a_reader_needs(self) -> None:
|
|
document = manifest_document({})
|
|
self.assertEqual(
|
|
document["layout"],
|
|
{
|
|
"files_dir": FILES_DIR,
|
|
"sql_dir": SQL_DIR,
|
|
"dump_suffix": DUMP_SUFFIX,
|
|
"cluster_suffix": CLUSTER_SUFFIX,
|
|
"dump_compression": "gzip",
|
|
},
|
|
)
|
|
|
|
def test_dumps_are_named_as_gzip_and_the_legacy_names_stay_known(self) -> None:
|
|
self.assertEqual(DUMP_SUFFIX, ".backup.sql.gz")
|
|
self.assertEqual(CLUSTER_SUFFIX, ".cluster.backup.sql.gz")
|
|
self.assertEqual(LEGACY_DUMP_SUFFIX, ".backup.sql")
|
|
self.assertEqual(LEGACY_CLUSTER_SUFFIX, ".cluster.backup.sql")
|
|
|
|
def test_the_schema_stays_one_so_existing_readers_keep_reading(self) -> None:
|
|
self.assertEqual(MANIFEST_SCHEMA, 1)
|
|
|
|
def test_it_carries_a_schema_so_a_reader_can_refuse_a_newer_one(self) -> None:
|
|
self.assertEqual(manifest_document({})["schema"], MANIFEST_SCHEMA)
|
|
|
|
def test_it_sorts_volumes_so_two_runs_produce_the_same_bytes(self) -> None:
|
|
state = VolumeOutcome(database=False, dumped=False)
|
|
document = manifest_document({"b": state, "a": state})
|
|
self.assertEqual(list(document["volumes"]), ["a", "b"])
|
|
|
|
|
|
class TestWriteManifest(unittest.TestCase):
|
|
def test_it_writes_readable_json_next_to_the_volumes(self) -> None:
|
|
with tempfile.TemporaryDirectory() as version_dir:
|
|
path = write_manifest(
|
|
version_dir,
|
|
{
|
|
"pgdata": VolumeOutcome(
|
|
database=True, dumped=False, engine="postgres"
|
|
)
|
|
},
|
|
)
|
|
self.assertEqual(Path(path).name, MANIFEST_FILE)
|
|
document = json.loads(Path(path).read_text(encoding="utf-8"))
|
|
self.assertEqual(
|
|
document["volumes"]["pgdata"],
|
|
{"database": True, "dumped": False, "engine": "postgres"},
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|