feat(v2): complete v2 reimplementation
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import stat
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from backup_tool.config import Settings
|
||||
|
||||
snapshot = importlib.import_module("backup_tool.snapshot")
|
||||
|
||||
|
||||
def settings_for(tmp_path: Path) -> Settings:
|
||||
key = tmp_path / "master.key"
|
||||
key.write_bytes(b"m6-restore-path-test-master-key-material")
|
||||
key.chmod(0o600)
|
||||
repositories = tmp_path / "repositories"
|
||||
sources = tmp_path / "sources"
|
||||
restores = tmp_path / "restores"
|
||||
for directory in (repositories, sources, restores):
|
||||
directory.mkdir()
|
||||
return Settings(
|
||||
data_dir=tmp_path,
|
||||
database_url=f"sqlite+aiosqlite:///{tmp_path / 'metadata.db'}",
|
||||
repository_roots=(repositories,),
|
||||
local_source_roots=(sources,),
|
||||
restore_roots=(restores,),
|
||||
master_key_file=key,
|
||||
min_free_bytes=1,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("name", ["existing", "outside", "root"])
|
||||
def test_restore_destination_rejects_existing_or_outside_paths(tmp_path: Path, name: str) -> None:
|
||||
settings = settings_for(tmp_path)
|
||||
root = settings.restore_roots[0]
|
||||
outside = tmp_path / "outside"
|
||||
outside.mkdir()
|
||||
existing = root / "existing"
|
||||
existing.mkdir()
|
||||
destinations = {
|
||||
"existing": existing,
|
||||
"outside": outside / "restore",
|
||||
"root": root,
|
||||
}
|
||||
|
||||
with pytest.raises(snapshot.SnapshotError):
|
||||
snapshot.validate_restore_destination(settings, str(destinations[name]))
|
||||
|
||||
|
||||
def test_restore_strips_special_permission_bits(tmp_path: Path) -> None:
|
||||
target = tmp_path / "restored"
|
||||
target.write_bytes(b"content")
|
||||
|
||||
snapshot._apply_metadata(
|
||||
target,
|
||||
{"metadata_support": ["mode"], "mode": 0o7777},
|
||||
)
|
||||
|
||||
mode = stat.S_IMODE(target.stat().st_mode)
|
||||
assert mode == 0o777
|
||||
assert mode & (stat.S_ISUID | stat.S_ISGID | stat.S_ISVTX) == 0
|
||||
|
||||
|
||||
def test_restore_destination_rejects_a_symlinked_parent(tmp_path: Path) -> None:
|
||||
settings = settings_for(tmp_path)
|
||||
outside = tmp_path / "outside"
|
||||
outside.mkdir()
|
||||
(settings.restore_roots[0] / "linked").symlink_to(outside, target_is_directory=True)
|
||||
|
||||
with pytest.raises(snapshot.SnapshotError):
|
||||
snapshot.validate_restore_destination(
|
||||
settings, str(settings.restore_roots[0] / "linked" / "restore")
|
||||
)
|
||||
Reference in New Issue
Block a user