llm-connect/tests/test_exceptions.py

97 lines
2.9 KiB
Python
Raw Normal View History

"""
Tests for the LLMError exception hierarchy (Core).
"""
import pytest
from llm_connect.exceptions import (
LLMError,
LLMConfigurationError,
LLMAPIError,
LLMRateLimitError,
LLMTimeoutError,
LLMSubprocessError,
)
class TestLLMErrorHierarchy:
def test_all_are_subclasses_of_llm_error(self):
assert issubclass(LLMConfigurationError, LLMError)
assert issubclass(LLMAPIError, LLMError)
assert issubclass(LLMRateLimitError, LLMError)
assert issubclass(LLMTimeoutError, LLMError)
assert issubclass(LLMSubprocessError, LLMError)
def test_rate_limit_is_api_error(self):
assert issubclass(LLMRateLimitError, LLMAPIError)
def test_all_are_exceptions(self):
assert issubclass(LLMError, Exception)
class TestLLMError:
def test_basic_message(self):
err = LLMError("something went wrong")
assert str(err) == "something went wrong"
def test_context_appears_in_str(self):
err = LLMError("oops", context={"provider": "openai"})
assert "provider=openai" in str(err)
def test_cause_is_chained(self):
cause = ValueError("root cause")
err = LLMError("wrapper", cause=cause)
assert err.__cause__ is cause
def test_empty_context_does_not_appear(self):
err = LLMError("clean message", context={})
assert str(err) == "clean message"
class TestLLMAPIError:
def test_has_status_code(self):
err = LLMAPIError("bad request", status_code=400)
assert err.status_code == 400
def test_has_response_body(self):
err = LLMAPIError("error", status_code=500, response_body='{"error": "oops"}')
assert err.response_body == '{"error": "oops"}'
def test_defaults(self):
err = LLMAPIError("minimal")
assert err.status_code == 0
assert err.response_body == ""
def test_rate_limit_inherits_status_code(self):
err = LLMRateLimitError("too many", status_code=429)
assert err.status_code == 429
assert isinstance(err, LLMAPIError)
class TestLLMSubprocessError:
def test_has_return_code(self):
err = LLMSubprocessError("cli failed", return_code=1)
assert err.return_code == 1
def test_has_stderr(self):
err = LLMSubprocessError("cli failed", stderr="error output")
assert err.stderr == "error output"
def test_defaults(self):
err = LLMSubprocessError("minimal")
assert err.return_code == 1
assert err.stderr == ""
class TestRaiseAndCatch:
def test_catch_as_llm_error(self):
with pytest.raises(LLMError):
raise LLMConfigurationError("no key")
def test_catch_api_error_as_llm_error(self):
with pytest.raises(LLMError):
raise LLMAPIError("http error", status_code=502)
def test_catch_rate_limit_as_api_error(self):
with pytest.raises(LLMAPIError):
raise LLMRateLimitError("429", status_code=429)