"""Unit tests for AnalyzeHandler.classify (issue 002). Verifies that every canonical LLM error class — no matter which provider module re-exports it — maps to the correct FailureClass, and that the ollama_cloud/yandex_gpt hierarchies are the same canonical classes. """ from __future__ import annotations from unittest.mock import MagicMock import pytest from contract_check.core.llm import errors as llm_errors from contract_check.core.llm import ollama_cloud, yandex_gpt from contract_check.worker_analyze.handler import AnalyzeHandler def _handler() -> AnalyzeHandler: return AnalyzeHandler(session_factory=MagicMock()) @pytest.mark.parametrize( ("error_class", "expected"), [ (llm_errors.LLMQuotaError, "llm_quota"), (llm_errors.LLMConfigError, "infra"), (llm_errors.LLMUnavailableError, "llm_timeout"), (llm_errors.LLMError, "llm_invalid_output"), ], ) @pytest.mark.parametrize("provider_module", [ollama_cloud, yandex_gpt]) def test_classify_llm_errors_from_both_providers( error_class: type[Exception], expected: str, provider_module: object ) -> None: """Re-exported classes from either provider must classify identically.""" handler = _handler() raised = error_class("boom") assert handler.classify(raised) == expected def test_provider_hierarchies_are_canonical() -> None: """Both adapters must re-export the same canonical error classes.""" assert ollama_cloud.LLMError is llm_errors.LLMError assert ollama_cloud.LLMQuotaError is llm_errors.LLMQuotaError assert ollama_cloud.LLMUnavailableError is llm_errors.LLMUnavailableError assert ollama_cloud.LLMConfigError is llm_errors.LLMConfigError assert yandex_gpt.LLMError is llm_errors.LLMError assert yandex_gpt.LLMQuotaError is llm_errors.LLMQuotaError assert yandex_gpt.LLMUnavailableError is llm_errors.LLMUnavailableError assert yandex_gpt.LLMConfigError is llm_errors.LLMConfigError def test_classify_unknown_error_is_infra() -> None: assert _handler().classify(RuntimeError("boom")) == "infra"