download re implemented
This commit is contained in:
@@ -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."""
|
||||
|
||||
Reference in New Issue
Block a user