Files
team-tryouts/tests/test_filesystem_roots.py

143 lines
5.5 KiB
Python

"""Where the application puts its files, and who agrees about it.
OBS-006. Three roots were built as `os.path.join(os.getcwd(), …)`: the
document store, the log directory and the backup directory. Each therefore
moved with whatever directory the process was started from — and the
processes that start this application are Waitress under Pterodactyl, a task
scheduler, pytest, and a person in a shell. Only one of the four is reliably
in the project directory.
The document store was fixed in wave G. The other two were not, and the gap
that opened between them is the reason this file exists: `backup.py` kept
archiving `./documents` while the application wrote to `DOCUMENTS_ROOT`.
The script now resolves the shared root and fails the run when it is absent.
"""
import os
import pytest
from app.storage import backups_root, documents_root, logs_root, project_root
class TestTheProjectAnchor:
def test_it_is_the_directory_holding_the_app_package(self):
assert os.path.isdir(os.path.join(project_root(), 'app'))
def test_it_does_not_follow_the_working_directory(self, tmp_path, monkeypatch):
"""The whole point. Every root below inherits this."""
before = project_root()
monkeypatch.chdir(tmp_path)
assert project_root() == before
@pytest.mark.parametrize(
('root', 'env_name', 'default_name'),
[
(documents_root, 'DOCUMENTS_ROOT', 'documents'),
(logs_root, 'LOG_DIR', 'logs'),
(backups_root, 'BACKUP_DIR', 'backups'),
],
)
class TestEachRoot:
def test_it_defaults_beside_the_project(self, root, env_name, default_name, monkeypatch):
monkeypatch.delenv(env_name, raising=False)
assert root() == os.path.join(project_root(), default_name)
def test_it_ignores_the_working_directory(
self, root, env_name, default_name, tmp_path, monkeypatch
):
monkeypatch.delenv(env_name, raising=False)
monkeypatch.chdir(tmp_path)
assert root() == os.path.join(project_root(), default_name)
assert not root().startswith(str(tmp_path))
def test_the_environment_wins(self, root, env_name, default_name, tmp_path, monkeypatch):
monkeypatch.setenv(env_name, str(tmp_path / 'elsewhere'))
assert root() == os.path.abspath(str(tmp_path / 'elsewhere'))
class TestTheBackupScriptAgreesWithTheApplication:
"""The regression this file was written for.
`backup.py` held its own `os.getcwd()`-based constant, so the two
answers to "where are the contracts" could differ — and did, for anyone
who set DOCUMENTS_ROOT because docs/deployment.md said to.
"""
def test_it_archives_the_directory_the_application_writes_to(self, tmp_path, monkeypatch):
from app.supporting_scripts import backup
store = tmp_path / 'somewhere-else' / 'documents'
(store / 'contrats signés').mkdir(parents=True)
(store / 'contrats signés' / 'a.pdf').write_bytes(b'%PDF-1.4 test')
monkeypatch.setenv('DOCUMENTS_ROOT', str(store))
monkeypatch.setattr(backup, 'BACKUP_DIR', str(tmp_path / 'backups'))
(tmp_path / 'backups').mkdir()
archive = backup.backup_documents()
assert archive is not None, (
'the script skipped, which is what it did on production while reporting success'
)
assert os.path.getsize(archive) > 0
def test_the_archive_actually_contains_the_contract(self, tmp_path, monkeypatch):
"""An empty zip is still a file of non-zero size. This is the
assertion that would have caught the original defect."""
import zipfile
from app.supporting_scripts import backup
store = tmp_path / 'documents'
(store / 'contrats signés').mkdir(parents=True)
(store / 'contrats signés' / 'contrat.pdf').write_bytes(b'%PDF-1.4 test')
monkeypatch.setenv('DOCUMENTS_ROOT', str(store))
monkeypatch.setattr(backup, 'BACKUP_DIR', str(tmp_path / 'backups'))
(tmp_path / 'backups').mkdir()
archive = backup.backup_documents()
with zipfile.ZipFile(archive) as zf:
assert any(name.endswith('contrat.pdf') for name in zf.namelist())
def test_a_missing_store_names_the_path_it_looked_in(self, tmp_path, monkeypatch):
"""A missing configured store is an actionable failure, not a skip."""
from app.supporting_scripts import backup
missing = tmp_path / 'not-here'
monkeypatch.setenv('DOCUMENTS_ROOT', str(missing))
with pytest.raises(backup.BackupError, match=str(missing).replace('\\', '\\\\')):
backup.backup_documents()
class TestLogsFollowTheSameRule:
def test_configure_logging_writes_where_logs_root_says(self, tmp_path, monkeypatch):
from app.app import create_app
target = tmp_path / 'var' / 'log'
monkeypatch.setenv('LOG_DIR', str(target))
create_app(
{
'SECRET_KEY': 'test-secret-not-used-anywhere-real',
'SQLALCHEMY_DATABASE_URI': f'sqlite:///{tmp_path / "t.sqlite"}',
'TESTING': True,
'WTF_CSRF_ENABLED': False,
'FORCE_HTTPS': False,
'SESSION_COOKIE_SECURE': False,
'ENABLE_DISCORD_BOT': False,
'AUTO_CREATE_TABLES': True,
'CORS_ALLOWED_ORIGINS': '',
'RATELIMIT_ENABLED': False,
}
)
assert target.is_dir(), 'the log directory is created where LOG_DIR points'
assert (target / 'app.log').exists()