tests: isolate the database so the suite can never touch the real DB
Several tests exercise modules (e.g. album_mbid_cache) that call get_database() with no path, which resolves to the real database/music_library.db. Running those writers against the live DB over a WSL-mounted Windows drive corrupted a user's library. conftest never isolated the DB path. conftest.py now sets os.environ['DATABASE_PATH'] to a throwaway temp file at import time (before any test module loads). MusicDatabase resolves its default path from DATABASE_PATH, so EVERY default-path MusicDatabase()/get_database() call in the suite now lands in /tmp — the real DB is never opened. Temp dir is removed at exit. Guard tests assert DATABASE_PATH, MusicDatabase().database_path, and get_database().database_path all resolve into the temp dir and never to database/music_library.db. (album_mbid_cache tests, which were failing against the corrupted live DB, now pass clean on the isolated temp DB.)
This commit is contained in:
parent
efe3895d5d
commit
22f30d3f40
2 changed files with 55 additions and 0 deletions
|
|
@ -4,6 +4,29 @@ Creates a minimal Flask+SocketIO app that replicates the relevant
|
|||
endpoints and event handlers without importing the full web_server.py
|
||||
(which would try to initialize Spotify, Soulseek, Plex, etc.)."""
|
||||
|
||||
# ── TEST-DATABASE ISOLATION — MUST run before any other import ─────────────
|
||||
# Force every MusicDatabase()/get_database() call in the suite onto a throwaway
|
||||
# temp database so a test can NEVER open or write the real
|
||||
# database/music_library.db. MusicDatabase resolves its default path from
|
||||
# os.environ['DATABASE_PATH'] (see database/music_database.py); setting it here,
|
||||
# at conftest import (before any test module loads), redirects ALL default-path
|
||||
# DB access to /tmp.
|
||||
#
|
||||
# Why this is non-negotiable: tests exercise modules (e.g. album_mbid_cache)
|
||||
# that call get_database() with no path → the real DB. Running those writers
|
||||
# against the live DB over a WSL-mounted Windows drive corrupted a user's
|
||||
# library. This guarantees it can't recur — tests get their own disposable DB.
|
||||
import os as _os
|
||||
import tempfile as _tempfile
|
||||
import atexit as _atexit
|
||||
import shutil as _shutil
|
||||
|
||||
if not _os.environ.get('SOULSYNC_TEST_DB_READY'):
|
||||
_TEST_DB_DIR = _tempfile.mkdtemp(prefix='soulsync-testdb-')
|
||||
_os.environ['DATABASE_PATH'] = _os.path.join(_TEST_DB_DIR, 'test_music_library.db')
|
||||
_os.environ['SOULSYNC_TEST_DB_READY'] = '1'
|
||||
_atexit.register(lambda: _shutil.rmtree(_TEST_DB_DIR, ignore_errors=True))
|
||||
|
||||
import copy
|
||||
import pytest
|
||||
import threading
|
||||
|
|
|
|||
32
tests/test_db_isolation_guard.py
Normal file
32
tests/test_db_isolation_guard.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
"""Guard: the test suite must NEVER resolve the real database/music_library.db.
|
||||
|
||||
Tests exercise modules that call get_database() with no path. If that resolves
|
||||
to the live DB, test writes can corrupt a real library (this happened, over a
|
||||
WSL-mounted Windows drive). conftest.py sets DATABASE_PATH to a temp file before
|
||||
anything imports; these tests prove it sticks for every default-path access.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
_REAL = os.path.join('database', 'music_library.db')
|
||||
|
||||
|
||||
def test_database_path_env_is_isolated():
|
||||
p = os.environ.get('DATABASE_PATH', '')
|
||||
assert 'soulsync-testdb-' in p, f"DATABASE_PATH not isolated: {p!r}"
|
||||
|
||||
|
||||
def test_musicdatabase_default_path_never_real():
|
||||
from database.music_database import MusicDatabase
|
||||
resolved = str(Path(MusicDatabase().database_path).resolve())
|
||||
assert 'soulsync-testdb-' in resolved, resolved
|
||||
assert not resolved.replace('\\', '/').endswith('database/music_library.db'), resolved
|
||||
|
||||
|
||||
def test_get_database_path_never_real():
|
||||
from database.music_database import get_database
|
||||
resolved = str(Path(get_database().database_path).resolve())
|
||||
assert 'soulsync-testdb-' in resolved, resolved
|
||||
Loading…
Reference in a new issue