| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- """
- Unit tests for the resume tracker module.
- Tests cover resume state tracking and loading.
- """
- import sys
- from unittest.mock import Mock
- from pathlib import Path
- import json
- import tempfile
- # Mock torch and transformers before importing
- sys_mock = Mock()
- sys.modules["torch"] = sys_mock
- sys.modules["transformers"] = sys_mock
- import pytest
- from src.translator.resume_tracker import ResumeTracker, ResumeState
- class TestResumeState:
- """Test cases for ResumeState dataclass."""
- def test_create_resume_state(self):
- """Test creating a resume state."""
- state = ResumeState(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=None,
- total_chapters=100,
- )
- assert state.work_id == "test_work"
- assert state.last_completed_index == 10
- assert state.last_failed_index is None
- assert state.total_chapters == 100
- def test_to_dict(self):
- """Test converting resume state to dictionary."""
- state = ResumeState(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=None,
- total_chapters=100,
- resume_message="Test message",
- )
- data = state.to_dict()
- assert data["work_id"] == "test_work"
- assert data["last_completed_index"] == 10
- assert data["last_failed_index"] is None
- assert data["total_chapters"] == 100
- assert data["resume_message"] == "Test message"
- assert "timestamp" in data
- def test_from_dict(self):
- """Test creating resume state from dictionary."""
- data = {
- "work_id": "test_work",
- "last_completed_index": 10,
- "last_failed_index": None,
- "total_chapters": 100,
- "timestamp": "2024-01-01T00:00:00",
- "resume_message": "Test message",
- }
- state = ResumeState.from_dict(data)
- assert state.work_id == "test_work"
- assert state.last_completed_index == 10
- assert state.total_chapters == 100
- def test_get_resume_index_with_failure(self):
- """Test getting resume index when there's a failed chapter."""
- state = ResumeState(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=15,
- total_chapters=100,
- )
- assert state.get_resume_index() == 15
- def test_get_resume_index_without_failure(self):
- """Test getting resume index when there's no failed chapter."""
- state = ResumeState(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=None,
- total_chapters=100,
- )
- assert state.get_resume_index() == 11
- def test_is_resumable_with_remaining(self):
- """Test is_resumable when there are remaining chapters."""
- state = ResumeState(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=None,
- total_chapters=100,
- )
- assert state.is_resumable() is True
- def test_is_resumable_complete(self):
- """Test is_resumable when all chapters are complete."""
- state = ResumeState(
- work_id="test_work",
- last_completed_index=99,
- last_failed_index=None,
- total_chapters=100,
- )
- assert state.is_resumable() is False
- class TestResumeTracker:
- """Test cases for ResumeTracker class."""
- @pytest.fixture
- def temp_dir(self):
- """Create a temporary directory for testing."""
- with tempfile.TemporaryDirectory() as tmp:
- yield Path(tmp)
- @pytest.fixture
- def tracker(self, temp_dir):
- """Create a resume tracker for testing."""
- return ResumeTracker(temp_dir)
- def test_init(self, temp_dir):
- """Test ResumeTracker initialization."""
- tracker = ResumeTracker(temp_dir)
- assert tracker.storage_dir == temp_dir
- assert tracker.resume_dir == temp_dir / "resume"
- assert tracker.resume_dir.exists()
- def test_save_resume_state(self, tracker):
- """Test saving resume state."""
- state = tracker.save_resume_state(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=None,
- total_chapters=100,
- )
- assert state.work_id == "test_work"
- assert state.last_completed_index == 10
- assert "Resume from chapter" in state.resume_message
- # Check file was created
- resume_file = tracker._get_resume_file_path("test_work")
- assert resume_file.exists()
- def test_load_resume_state(self, tracker):
- """Test loading resume state."""
- # Save state first
- tracker.save_resume_state(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=None,
- total_chapters=100,
- )
- # Load it back
- loaded = tracker.load_resume_state("test_work")
- assert loaded is not None
- assert loaded.work_id == "test_work"
- assert loaded.last_completed_index == 10
- assert loaded.total_chapters == 100
- def test_load_nonexistent_resume_state(self, tracker):
- """Test loading a non-existent resume state."""
- loaded = tracker.load_resume_state("nonexistent")
- assert loaded is None
- def test_delete_resume_state(self, tracker):
- """Test deleting resume state."""
- # Save state first
- tracker.save_resume_state(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=None,
- total_chapters=100,
- )
- # Delete it
- tracker.delete_resume_state("test_work")
- # Check it's gone
- resume_file = tracker._get_resume_file_path("test_work")
- assert not resume_file.exists()
- def test_get_resume_index(self, tracker):
- """Test getting resume index."""
- # Save state first
- tracker.save_resume_state(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=None,
- total_chapters=100,
- )
- # Get resume index
- index = tracker.get_resume_index("test_work", 100)
- assert index == 11
- def test_get_resume_index_nonexistent(self, tracker):
- """Test getting resume index for non-existent state."""
- index = tracker.get_resume_index("nonexistent", 100)
- assert index is None
- def test_update_on_chapter_complete(self, tracker):
- """Test updating state on chapter completion."""
- tracker.update_on_chapter_complete(
- work_id="test_work",
- chapter_index=5,
- total_chapters=100,
- )
- loaded = tracker.load_resume_state("test_work")
- assert loaded is not None
- assert loaded.last_completed_index == 5
- assert loaded.last_failed_index is None
- def test_update_on_chapter_failed(self, tracker):
- """Test updating state on chapter failure."""
- tracker.update_on_chapter_failed(
- work_id="test_work",
- chapter_index=5,
- total_chapters=100,
- )
- loaded = tracker.load_resume_state("test_work")
- assert loaded is not None
- assert loaded.last_failed_index == 5
- def test_generate_resume_message_with_failure(self):
- """Test generating resume message with failed chapter."""
- state = ResumeState(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=15,
- total_chapters=100,
- )
- tracker = ResumeTracker(Path("/tmp"))
- message = tracker._generate_resume_message(state)
- assert "failed chapter 15" in message
- assert "85" in message # remaining chapters
- def test_generate_resume_message_without_failure(self):
- """Test generating resume message without failed chapter."""
- state = ResumeState(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=None,
- total_chapters=100,
- )
- tracker = ResumeTracker(Path("/tmp"))
- message = tracker._generate_resume_message(state)
- assert "Resume from chapter 11" in message
- assert "89" in message # remaining chapters
- def test_get_all_resume_states(self, tracker):
- """Test getting all resume states."""
- # Save multiple states
- tracker.save_resume_state("work1", 10, None, 100)
- tracker.save_resume_state("work2", 20, None, 200)
- states = tracker.get_all_resume_states()
- assert len(states) == 2
- work_ids = {s.work_id for s in states}
- assert work_ids == {"work1", "work2"}
- def test_clear_all_resume_states(self, tracker):
- """Test clearing all resume states."""
- # Save multiple states
- tracker.save_resume_state("work1", 10, None, 100)
- tracker.save_resume_state("work2", 20, None, 200)
- tracker.clear_all_resume_states()
- states = tracker.get_all_resume_states()
- assert len(states) == 0
- def test_update_existing_state_on_complete(self, tracker):
- """Test that updating state preserves existing data."""
- # Save initial state
- tracker.save_resume_state(
- work_id="test_work",
- last_completed_index=5,
- last_failed_index=7,
- total_chapters=100,
- )
- # Update on completion
- tracker.update_on_chapter_complete(
- work_id="test_work",
- chapter_index=10,
- total_chapters=100,
- )
- loaded = tracker.load_resume_state("test_work")
- assert loaded.last_completed_index == 10
- assert loaded.last_failed_index is None # Should be cleared
- def test_custom_resume_message(self, tracker):
- """Test saving state with custom resume message."""
- state = tracker.save_resume_state(
- work_id="test_work",
- last_completed_index=10,
- last_failed_index=None,
- total_chapters=100,
- resume_message="Custom message here",
- )
- assert state.resume_message == "Custom message here"
- def test_get_resume_file_path(self, tracker):
- """Test getting resume file path."""
- path = tracker._get_resume_file_path("test_work")
- assert path.name == "test_work_resume.json"
- assert path.parent == tracker.resume_dir
|