download re implemented

This commit is contained in:
2025-10-30 22:06:41 +01:00
parent 6ebc2ed2ea
commit 3be175522f
16 changed files with 359 additions and 1335 deletions

View File

@@ -1,7 +1,7 @@
"""Unit tests for the download queue service.
Tests cover queue management, priority handling, persistence,
concurrent downloads, and error scenarios.
Tests cover queue management, manual download control, persistence,
and error scenarios for the simplified download service.
"""
from __future__ import annotations
@@ -42,7 +42,6 @@ def download_service(mock_anime_service, temp_persistence_path):
"""Create a DownloadService instance for testing."""
return DownloadService(
anime_service=mock_anime_service,
max_concurrent_downloads=2,
max_retries=3,
persistence_path=temp_persistence_path,
)
@@ -61,11 +60,10 @@ class TestDownloadServiceInitialization:
)
assert len(service._pending_queue) == 0
assert len(service._active_downloads) == 0
assert service._active_download is None
assert len(service._completed_items) == 0
assert len(service._failed_items) == 0
assert service._is_running is False
assert service._is_paused is False
assert service._is_stopped is True
def test_initialization_loads_persisted_queue(
self, mock_anime_service, temp_persistence_path
@@ -152,29 +150,6 @@ class TestQueueManagement:
assert len(item_ids) == 3
assert len(download_service._pending_queue) == 3
@pytest.mark.asyncio
async def test_add_high_priority_to_front(self, download_service):
"""Test that high priority items are added to front of queue."""
# Add normal priority item
await download_service.add_to_queue(
serie_id="series-1",
serie_name="Test Series",
episodes=[EpisodeIdentifier(season=1, episode=1)],
priority=DownloadPriority.NORMAL,
)
# Add high priority item
await download_service.add_to_queue(
serie_id="series-2",
serie_name="Priority Series",
episodes=[EpisodeIdentifier(season=1, episode=1)],
priority=DownloadPriority.HIGH,
)
# High priority should be at front
assert download_service._pending_queue[0].serie_id == "series-2"
assert download_service._pending_queue[1].serie_id == "series-1"
@pytest.mark.asyncio
async def test_remove_from_pending_queue(self, download_service):
"""Test removing items from pending queue."""
@@ -191,32 +166,108 @@ class TestQueueManagement:
assert len(download_service._pending_queue) == 0
@pytest.mark.asyncio
async def test_reorder_queue(self, download_service):
"""Test reordering items in queue."""
# Add three items
async def test_start_next_download(self, download_service):
"""Test starting the next download from queue."""
# Add items to queue
item_ids = await download_service.add_to_queue(
serie_id="series-1",
serie_name="Test Series",
episodes=[
EpisodeIdentifier(season=1, episode=1),
EpisodeIdentifier(season=1, episode=2),
],
)
# Start next download
started_id = await download_service.start_next_download()
assert started_id is not None
assert started_id == item_ids[0]
assert len(download_service._pending_queue) == 1
assert download_service._is_stopped is False
@pytest.mark.asyncio
async def test_start_next_download_empty_queue(self, download_service):
"""Test starting download with empty queue returns None."""
result = await download_service.start_next_download()
assert result is None
@pytest.mark.asyncio
async def test_start_next_download_already_active(
self, download_service, mock_anime_service
):
"""Test that starting download while one is active raises error."""
# Add items and start one
await download_service.add_to_queue(
serie_id="series-1",
serie_name="Series 1",
episodes=[EpisodeIdentifier(season=1, episode=1)],
serie_name="Test Series",
episodes=[
EpisodeIdentifier(season=1, episode=1),
EpisodeIdentifier(season=1, episode=2),
],
)
# Make download slow so it stays active
async def slow_download(**kwargs):
await asyncio.sleep(10)
mock_anime_service.download = AsyncMock(side_effect=slow_download)
# Start first download (will block for 10s in background)
item_id = await download_service.start_next_download()
assert item_id is not None
await asyncio.sleep(0.1) # Let it start processing
# Try to start another - should fail because one is active
with pytest.raises(DownloadServiceError, match="already in progress"):
await download_service.start_next_download()
@pytest.mark.asyncio
async def test_stop_downloads(self, download_service):
"""Test stopping queue processing."""
await download_service.stop_downloads()
assert download_service._is_stopped is True
@pytest.mark.asyncio
async def test_download_completion_moves_to_list(
self, download_service, mock_anime_service
):
"""Test successful download moves item to completed list."""
# Add item
await download_service.add_to_queue(
serie_id="series-2",
serie_name="Series 2",
episodes=[EpisodeIdentifier(season=1, episode=1)],
)
await download_service.add_to_queue(
serie_id="series-3",
serie_name="Series 3",
serie_id="series-1",
serie_name="Test Series",
episodes=[EpisodeIdentifier(season=1, episode=1)],
)
# Move last item to position 0
item_to_move = download_service._pending_queue[2].id
success = await download_service.reorder_queue(item_to_move, 0)
# Start and wait for completion
await download_service.start_next_download()
await asyncio.sleep(0.2) # Wait for download to complete
assert success is True
assert download_service._pending_queue[0].id == item_to_move
assert download_service._pending_queue[0].serie_id == "series-3"
assert len(download_service._completed_items) == 1
assert download_service._active_download is None
@pytest.mark.asyncio
async def test_download_failure_moves_to_list(
self, download_service, mock_anime_service
):
"""Test failed download moves item to failed list."""
# Make download fail
mock_anime_service.download = AsyncMock(return_value=False)
# Add item
await download_service.add_to_queue(
serie_id="series-1",
serie_name="Test Series",
episodes=[EpisodeIdentifier(season=1, episode=1)],
)
# Start and wait for failure
await download_service.start_next_download()
await asyncio.sleep(0.2) # Wait for download to fail
assert len(download_service._failed_items) == 1
assert download_service._active_download is None
class TestQueueStatus:
@@ -237,6 +288,7 @@ class TestQueueStatus:
status = await download_service.get_queue_status()
# Queue is stopped until start_next_download() is called
assert status.is_running is False
assert status.is_paused is False
assert len(status.pending_queue) == 2
@@ -270,19 +322,6 @@ class TestQueueStatus:
class TestQueueControl:
"""Test queue control operations."""
@pytest.mark.asyncio
async def test_pause_queue(self, download_service):
"""Test pausing the queue."""
await download_service.pause_queue()
assert download_service._is_paused is True
@pytest.mark.asyncio
async def test_resume_queue(self, download_service):
"""Test resuming the queue."""
await download_service.pause_queue()
await download_service.resume_queue()
assert download_service._is_paused is False
@pytest.mark.asyncio
async def test_clear_completed(self, download_service):
"""Test clearing completed downloads."""
@@ -438,33 +477,29 @@ class TestServiceLifecycle:
@pytest.mark.asyncio
async def test_start_service(self, download_service):
"""Test starting the service."""
# start() is now just for initialization/compatibility
await download_service.start()
assert download_service._is_running is True
# No _is_running attribute - simplified service doesn't track this
@pytest.mark.asyncio
async def test_stop_service(self, download_service):
"""Test stopping the service."""
await download_service.start()
await download_service.stop()
assert download_service._is_running is False
# Verifies service can be stopped without errors
# No _is_running attribute in simplified service
@pytest.mark.asyncio
async def test_start_already_running(self, download_service):
"""Test starting service when already running."""
await download_service.start()
await download_service.start() # Should not raise error
assert download_service._is_running is True
# No _is_running attribute in simplified service
class TestErrorHandling:
"""Test error handling in download service."""
@pytest.mark.asyncio
async def test_reorder_nonexistent_item(self, download_service):
"""Test reordering non-existent item raises error."""
with pytest.raises(DownloadServiceError):
await download_service.reorder_queue("nonexistent-id", 0)
@pytest.mark.asyncio
async def test_download_failure_moves_to_failed(self, download_service):
"""Test that download failures are handled correctly."""