"""Check the offline copy commands against disposable instances and damaged files.""" import hashlib import json import os from pathlib import Path import queue import subprocess import sys import tempfile import threading import unittest class BackupTests(unittest.TestCase): def setUp(self): self.temp = tempfile.TemporaryDirectory() self.addCleanup(self.temp.cleanup) self.dir = Path(self.temp.name) self.source = self.dir / "original.ratdb" self.backup = self.dir / "backup.ratdb" self.restore = self.dir / "restored.ratdb" self.cli("init", self.source) self.cli("put", self.source, "cars", "001", '{"make":"Ford"}') def cli(self, *args, success=True): result = subprocess.run([EXE, *args], timeout=30, capture_output=True, text=True) self.assertEqual(result.returncode == 0, success, result.stderr) return result.stdout def test_roundtrip_no_overwrite(self): self.cli("backup", self.source, self.backup) digest = lambda p: hashlib.sha256(p.read_bytes()).digest() expected = digest(self.source) self.assertEqual(digest(self.backup), expected) self.cli("put", self.source, "cars", "001", '{"make":"newer"}') self.cli("backup", self.source, self.backup, success=False) self.cli("restore", self.backup, self.restore) self.assertEqual(digest(self.restore), expected) self.assertEqual(json.loads(self.cli("get", self.restore, "cars", "001"))["make"], "Ford") self.cli("restore", self.backup, self.source, success=False) self.assertEqual(json.loads(self.cli("get", self.source, "cars", "001"))["make"], "newer") self.assertFalse(Path(str(self.restore) + ".auth").exists()) def test_reject_invalid_input(self): self.cli("restore", self.backup, self.restore, success=False) self.assertFalse(self.backup.exists()) self.backup.touch() self.cli("restore", self.backup, self.restore, success=False) self.assertEqual(self.backup.stat().st_size, 0) self.assertFalse(self.restore.exists()) # Baseline v1 second generation resides in bank 1. with self.source.open("r+b") as f: f.seek(self.source.stat().st_size // 2 + 64 + 12) b = f.read(1) f.seek(-1, 1) f.write(bytes([b[0] ^ 1])) self.cli("backup", self.source, self.restore, success=False) self.assertFalse(self.restore.exists()) def test_refuse_credential_sidecar_and_busy_source(self): orphan = Path(str(self.backup) + ".auth") orphan.write_bytes(b"preserve") self.cli("backup", self.source, self.backup, success=False) self.assertEqual(orphan.read_bytes(), b"preserve") self.assertFalse(self.backup.exists()) subprocess.run([EXE, "setup", self.source, "admin"], timeout=30, check=True, capture_output=True, env={**os.environ, "RATDB_PASSWORD": "disposable local credential"}) server = subprocess.Popen([EXE, "serve", self.source, "--bind", "127.0.0.1:0"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) try: ready = queue.Queue() threading.Thread(target=lambda: ready.put(server.stdout.readline()), daemon=True).start() self.assertIn(b"listening on", ready.get(timeout=15)) self.cli("backup", self.source, self.restore, success=False) self.assertFalse(self.restore.exists()) finally: server.kill() server.communicate(timeout=10) if __name__ == "__main__": EXE = Path(sys.argv.pop(1)).resolve() unittest.main()