108 lines
3.3 KiB
Python
108 lines
3.3 KiB
Python
import asyncio
|
|
from unittest.mock import AsyncMock, MagicMock, patch
|
|
|
|
import pytest
|
|
|
|
|
|
TEST_MBID = "cc197bad-dc9c-440d-a5b5-d52ba2e14234"
|
|
|
|
|
|
def _make_settings(audiodb_enabled: bool = True):
|
|
s = MagicMock()
|
|
s.audiodb_enabled = audiodb_enabled
|
|
return s
|
|
|
|
|
|
def _make_prefs(settings=None, cursor=None):
|
|
if settings is None:
|
|
settings = _make_settings()
|
|
prefs = MagicMock()
|
|
prefs.get_advanced_settings.return_value = settings
|
|
prefs.get_setting = MagicMock(return_value=cursor)
|
|
prefs.save_setting = MagicMock()
|
|
return prefs
|
|
|
|
|
|
def _make_library_db(artists=None, albums=None):
|
|
cache = AsyncMock()
|
|
cache.get_artists = AsyncMock(return_value=artists or [])
|
|
cache.get_albums = AsyncMock(return_value=albums or [])
|
|
return cache
|
|
|
|
|
|
class TestSweepSkipsWhenDisabled:
|
|
@pytest.mark.asyncio
|
|
async def test_disabled_skips(self):
|
|
from core.tasks import warm_audiodb_cache_periodically
|
|
|
|
settings = _make_settings(audiodb_enabled=False)
|
|
prefs = _make_prefs(settings)
|
|
svc = AsyncMock()
|
|
cache = _make_library_db()
|
|
|
|
task = asyncio.create_task(
|
|
warm_audiodb_cache_periodically(svc, cache, prefs)
|
|
)
|
|
# Replace sleep to avoid 120s wait
|
|
with patch('core.tasks.asyncio.sleep', new_callable=AsyncMock) as mock_sleep:
|
|
mock_sleep.side_effect = [None, asyncio.CancelledError()]
|
|
try:
|
|
await task
|
|
except asyncio.CancelledError:
|
|
pass
|
|
|
|
svc.fetch_and_cache_artist_images.assert_not_called()
|
|
|
|
|
|
class TestSweepSkipsEmptyLibrary:
|
|
@pytest.mark.asyncio
|
|
async def test_empty_library_skips(self):
|
|
from core.tasks import warm_audiodb_cache_periodically
|
|
|
|
prefs = _make_prefs()
|
|
svc = AsyncMock()
|
|
cache = _make_library_db(artists=[], albums=[])
|
|
|
|
task = asyncio.create_task(
|
|
warm_audiodb_cache_periodically(svc, cache, prefs)
|
|
)
|
|
with patch('core.tasks.asyncio.sleep', new_callable=AsyncMock) as mock_sleep:
|
|
mock_sleep.side_effect = [None, asyncio.CancelledError()]
|
|
try:
|
|
await task
|
|
except asyncio.CancelledError:
|
|
pass
|
|
|
|
svc.get_cached_artist_images.assert_not_called()
|
|
|
|
|
|
class TestSweepCursorPersistence:
|
|
@pytest.mark.asyncio
|
|
async def test_cursor_saved_on_completion(self):
|
|
from core.tasks import warm_audiodb_cache_periodically
|
|
|
|
prefs = _make_prefs()
|
|
svc = AsyncMock()
|
|
svc.get_cached_artist_images = AsyncMock(return_value=None)
|
|
svc.fetch_and_cache_artist_images = AsyncMock(return_value=None)
|
|
|
|
artists = [{"mbid": TEST_MBID, "name": "Coldplay"}]
|
|
cache = _make_library_db(artists=artists)
|
|
|
|
call_count = 0
|
|
async def smart_sleep(duration):
|
|
nonlocal call_count
|
|
call_count += 1
|
|
if call_count >= 4:
|
|
raise asyncio.CancelledError()
|
|
|
|
with patch('core.tasks.asyncio.sleep', side_effect=smart_sleep):
|
|
try:
|
|
await warm_audiodb_cache_periodically(svc, cache, prefs)
|
|
except asyncio.CancelledError:
|
|
pass
|
|
|
|
save_calls = prefs.save_setting.call_args_list
|
|
cursor_clears = [c for c in save_calls if c[0] == ('audiodb_sweep_cursor', None)]
|
|
assert len(cursor_clears) >= 1
|