cura-te-ipsum/tests/test_backups.py
2021-11-13 07:39:23 +03:00

204 lines
8.2 KiB
Python

import os
import random
import string
import tempfile
from unittest import TestCase, mock
from datetime import datetime
import curateipsum.backup as bk
import curateipsum.fs as fs
class TestBackupCleanup(TestCase):
def setUp(self) -> None:
self.backup_dir = tempfile.TemporaryDirectory(prefix="backup_")
def tearDown(self) -> None:
self.backup_dir.cleanup()
def _add_backup(self, backup_name: str) -> fs.PseudoDirEntry:
backup = fs.PseudoDirEntry(os.path.join(self.backup_dir.name, backup_name))
os.mkdir(backup.path)
fd, path = tempfile.mkstemp(prefix="backup_file_", dir=backup.path)
with open(fd, "w") as f:
f.write(''.join(random.choices(string.printable, k=128)))
return backup
@staticmethod
def _check_backup_not_empty(backup: fs.PseudoDirEntry) -> bool:
return bool(os.listdir(backup.path))
def _check_backups(self, expected_backups):
backups_list = os.listdir(self.backup_dir.name)
self.assertEqual(sorted(b.name for b in expected_backups),
sorted(backups_list))
for b in expected_backups:
self.assertTrue(self._check_backup_not_empty(b))
def _run_cleanup(self, **kwargs):
""" Run cleanup_old_backups with null parameters. """
cleanup_kwargs = {
"backup_dir": self.backup_dir.name,
"dry_run": False,
"keep_all": None,
"keep_daily": None,
"keep_weekly": None,
"keep_monthly": None,
"keep_yearly": None,
}
cleanup_kwargs.update(**kwargs)
bk.cleanup_old_backups(**cleanup_kwargs)
def test_no_backups(self):
""" Test behaviour with no available backups """
bk.cleanup_old_backups(self.backup_dir.name)
self.assertFalse(os.listdir(self.backup_dir.name))
@mock.patch(f"{bk.__name__}.datetime", wraps=datetime)
def test_only_one_backup(self, mock_datetime):
""" Test the only backup will not be removed in any case """
mock_datetime.now.return_value = datetime(2021, 10, 20)
only_backup = self._add_backup("20010101_0000")
self._run_cleanup(keep_all=1)
self._check_backups([only_backup])
@mock.patch(f"{bk.__name__}.datetime", wraps=datetime)
def test_at_least_one_should_be_left(self, mock_datetime):
""" Test at least one backup should be left """
mock_datetime.now.return_value = datetime(2021, 10, 20)
backups = [
self._add_backup("20211103_0300"),
self._add_backup("20201216_0100"),
self._add_backup("20200716_0100"),
self._add_backup("20181116_0100"),
]
expected_backups = [backups[0]]
self._run_cleanup()
self._check_backups(expected_backups)
@mock.patch(f"{bk.__name__}.datetime", wraps=datetime)
def test_keep_all_threshold_only(self, mock_datetime):
""" Test threshold for keeping all backups """
mock_datetime.now.return_value = datetime(2021, 10, 20)
backups = [
self._add_backup("20211019_0300"),
self._add_backup("20211017_0100"),
self._add_backup("20211016_2300"),
]
expected_backups = backups[:2]
self._run_cleanup(keep_all=3)
self._check_backups(expected_backups)
@mock.patch(f"{bk.__name__}.datetime", wraps=datetime)
def test_keep_daily_threshold_only(self, mock_datetime):
""" Test threshold for keeping daily backups """
mock_datetime.now.return_value = datetime(2021, 10, 20)
backups = [
self._add_backup("20211019_0300"),
self._add_backup("20211017_2100"),
self._add_backup("20211017_0100"),
self._add_backup("20211017_0030"),
self._add_backup("20211016_2300"),
self._add_backup("20211016_0100"),
]
expected_backups = [backups[0], backups[3]]
self._run_cleanup(keep_daily=3)
self._check_backups(expected_backups)
@mock.patch(f"{bk.__name__}.datetime", wraps=datetime)
def test_keep_all_and_daily_thresholds(self, mock_datetime):
""" Test threshold for keeping all and daily backups """
mock_datetime.now.return_value = datetime(2021, 10, 20)
backups = [
self._add_backup("20211019_0300"),
self._add_backup("20211017_0200"),
self._add_backup("20211017_0100"),
self._add_backup("20211016_2300"),
self._add_backup("20211016_2200"),
self._add_backup("20211015_2200"),
self._add_backup("20211015_1500"),
self._add_backup("20211015_0200"),
self._add_backup("20211014_2200"),
self._add_backup("20211014_2000"),
self._add_backup("20211014_1232"),
]
expected_backups = backups[0:3] + [backups[4]] + [backups[7]]
self._run_cleanup(keep_all=3, keep_daily=5)
self._check_backups(expected_backups)
@mock.patch(f"{bk.__name__}.datetime", wraps=datetime)
def test_keep_weekly_threshold_only(self, mock_datetime):
""" Test threshold for keeping weekly backups """
mock_datetime.now.return_value = datetime(2021, 11, 11)
backups = [
self._add_backup("20211111_0300"),
self._add_backup("20211110_0300"),
self._add_backup("20211108_0100"),
self._add_backup("20211107_2300"),
self._add_backup("20211107_0100"),
self._add_backup("20211031_0100"),
self._add_backup("20211025_0100"),
self._add_backup("20211024_0100"),
self._add_backup("20211023_0100"),
self._add_backup("20211022_0100"),
self._add_backup("20211008_0100"),
self._add_backup("20211007_0100"),
self._add_backup("20211004_0100"),
self._add_backup("20211003_0100"),
]
expected_backups = [backups[2], backups[4], backups[6],
backups[9], backups[12]]
self._run_cleanup(keep_weekly=5)
self._check_backups(expected_backups)
@mock.patch(f"{bk.__name__}.datetime", wraps=datetime)
def test_keep_monthly_threshold_only(self, mock_datetime):
""" Test threshold for keeping monthly backups """
mock_datetime.now.return_value = datetime(2021, 11, 11)
backups = [
self._add_backup("20211103_0300"),
self._add_backup("20211019_0300"),
self._add_backup("20211017_2100"),
self._add_backup("20211017_0100"),
self._add_backup("20210916_2300"),
self._add_backup("20210916_0100"),
self._add_backup("20210816_0100"),
self._add_backup("20210810_0000"),
self._add_backup("20210716_0100"),
]
expected_backups = [backups[0], backups[3], backups[5], backups[7]]
self._run_cleanup(keep_monthly=3)
self._check_backups(expected_backups)
@mock.patch(f"{bk.__name__}.datetime", wraps=datetime)
def test_keep_yearly_threshold_only(self, mock_datetime):
""" Test threshold for keeping yearly backups """
mock_datetime.now.return_value = datetime(2021, 11, 11)
backups = [
self._add_backup("20211103_0300"),
self._add_backup("20210810_0000"),
self._add_backup("20210716_0100"),
self._add_backup("20201216_0100"),
self._add_backup("20200716_0100"),
self._add_backup("20190316_0100"),
self._add_backup("20181116_0100"),
]
expected_backups = [backups[2], backups[4], backups[5], backups[6]]
self._run_cleanup(keep_yearly=3)
self._check_backups(expected_backups)
@mock.patch(f"{bk.__name__}.datetime", wraps=datetime)
def test_dry_run(self, mock_datetime):
""" Test dry run does not remove anything """
mock_datetime.now.return_value = datetime(2021, 11, 11)
backups = [
self._add_backup("20211103_0300"),
self._add_backup("20210810_0000"),
self._add_backup("20210716_0100"),
self._add_backup("20200716_0100"),
self._add_backup("20181116_0100"),
]
self._run_cleanup(keep_all=2, dry_run=True)
self._check_backups(backups)