"""Tests for context management exceptions.""" from app.services.context.exceptions import ( AssemblyTimeoutError, BudgetExceededError, CacheError, CompressionError, ContextError, ContextNotFoundError, FormattingError, InvalidContextError, ScoringError, TokenCountError, ) class TestContextError: """Tests for base ContextError.""" def test_basic_initialization(self) -> None: """Test basic error initialization.""" error = ContextError("Test error") assert error.message == "Test error" assert error.details == {} assert str(error) == "Test error" def test_with_details(self) -> None: """Test error with details.""" error = ContextError("Test error", {"key": "value", "count": 42}) assert error.details == {"key": "value", "count": 42} def test_to_dict(self) -> None: """Test conversion to dictionary.""" error = ContextError("Test error", {"key": "value"}) result = error.to_dict() assert result["error_type"] == "ContextError" assert result["message"] == "Test error" assert result["details"] == {"key": "value"} def test_inheritance(self) -> None: """Test that ContextError inherits from Exception.""" error = ContextError("Test") assert isinstance(error, Exception) class TestBudgetExceededError: """Tests for BudgetExceededError.""" def test_default_message(self) -> None: """Test default error message.""" error = BudgetExceededError() assert "exceeded" in error.message.lower() def test_with_budget_info(self) -> None: """Test with budget information.""" error = BudgetExceededError( allocated=1000, requested=1500, context_type="knowledge", ) assert error.allocated == 1000 assert error.requested == 1500 assert error.context_type == "knowledge" assert error.details["overage"] == 500 def test_to_dict_includes_budget_info(self) -> None: """Test that to_dict includes budget info.""" error = BudgetExceededError( allocated=1000, requested=1500, ) result = error.to_dict() assert result["details"]["allocated"] == 1000 assert result["details"]["requested"] == 1500 assert result["details"]["overage"] == 500 class TestTokenCountError: """Tests for TokenCountError.""" def test_basic_error(self) -> None: """Test basic token count error.""" error = TokenCountError() assert "token" in error.message.lower() def test_with_model_info(self) -> None: """Test with model information.""" error = TokenCountError( message="Failed to count", model="claude-3-sonnet", text_length=5000, ) assert error.model == "claude-3-sonnet" assert error.text_length == 5000 assert error.details["model"] == "claude-3-sonnet" class TestCompressionError: """Tests for CompressionError.""" def test_basic_error(self) -> None: """Test basic compression error.""" error = CompressionError() assert "compress" in error.message.lower() def test_with_token_info(self) -> None: """Test with token information.""" error = CompressionError( original_tokens=2000, target_tokens=1000, achieved_tokens=1500, ) assert error.original_tokens == 2000 assert error.target_tokens == 1000 assert error.achieved_tokens == 1500 class TestAssemblyTimeoutError: """Tests for AssemblyTimeoutError.""" def test_basic_error(self) -> None: """Test basic timeout error.""" error = AssemblyTimeoutError() assert "timed out" in error.message.lower() def test_with_timing_info(self) -> None: """Test with timing information.""" error = AssemblyTimeoutError( timeout_ms=100, elapsed_ms=150.5, stage="scoring", ) assert error.timeout_ms == 100 assert error.elapsed_ms == 150.5 assert error.stage == "scoring" assert error.details["stage"] == "scoring" class TestScoringError: """Tests for ScoringError.""" def test_basic_error(self) -> None: """Test basic scoring error.""" error = ScoringError() assert "score" in error.message.lower() def test_with_scorer_info(self) -> None: """Test with scorer information.""" error = ScoringError( scorer_type="relevance", context_id="ctx-123", ) assert error.scorer_type == "relevance" assert error.context_id == "ctx-123" class TestFormattingError: """Tests for FormattingError.""" def test_basic_error(self) -> None: """Test basic formatting error.""" error = FormattingError() assert "format" in error.message.lower() def test_with_model_info(self) -> None: """Test with model information.""" error = FormattingError( model="claude-3-opus", adapter="ClaudeAdapter", ) assert error.model == "claude-3-opus" assert error.adapter == "ClaudeAdapter" class TestCacheError: """Tests for CacheError.""" def test_basic_error(self) -> None: """Test basic cache error.""" error = CacheError() assert "cache" in error.message.lower() def test_with_operation_info(self) -> None: """Test with operation information.""" error = CacheError( operation="get", cache_key="ctx:abc123", ) assert error.operation == "get" assert error.cache_key == "ctx:abc123" class TestContextNotFoundError: """Tests for ContextNotFoundError.""" def test_basic_error(self) -> None: """Test basic not found error.""" error = ContextNotFoundError() assert "not found" in error.message.lower() def test_with_source_info(self) -> None: """Test with source information.""" error = ContextNotFoundError( source="knowledge-base", query="authentication flow", ) assert error.source == "knowledge-base" assert error.query == "authentication flow" class TestInvalidContextError: """Tests for InvalidContextError.""" def test_basic_error(self) -> None: """Test basic invalid error.""" error = InvalidContextError() assert "invalid" in error.message.lower() def test_with_field_info(self) -> None: """Test with field information.""" error = InvalidContextError( field="content", value="", reason="Content cannot be empty", ) assert error.field == "content" assert error.value == "" assert error.reason == "Content cannot be empty" def test_value_type_only_in_details(self) -> None: """Test that only value type is included in details (not actual value).""" error = InvalidContextError( field="api_key", value="secret-key-here", ) # Actual value should not be in details assert "secret-key-here" not in str(error.details) assert error.details["value_type"] == "str"