Files
free-claude-code/tests/test_error_mapping.py
T
Cursor Agent d3f5f8877f Phase 1: Extract shared provider utils into providers/common/
- Create providers/common/ with sse_builder, message_converter, think_parser,
  heuristic_tool_parser, error_mapping
- Update nvidia_nim/utils and errors to re-export from common for backward compat
- Update all provider clients and tests to import from providers.common
- Remove duplicated files from nvidia_nim/utils/

Co-authored-by: Ali Khokhar <alishahryar2@gmail.com>
2026-02-17 01:55:38 +00:00

123 lines
4.5 KiB
Python

"""Tests for providers/nvidia_nim/errors.py error mapping."""
import pytest
from unittest.mock import patch, MagicMock
import openai
from httpx import Response, Request
from providers.common import map_error
from providers.exceptions import (
AuthenticationError,
InvalidRequestError,
RateLimitError,
OverloadedError,
APIError,
)
def _make_openai_error(cls, message="test error", status_code=None):
"""Helper to create openai exceptions with required httpx objects."""
response = Response(
status_code=status_code or 500, request=Request("POST", "http://test")
)
body = {"error": {"message": message}}
# openai.APIError base class has a different constructor signature
if cls is openai.APIError:
return cls(message, request=Request("POST", "http://test"), body=body)
return cls(message, response=response, body=body)
class TestMapError:
"""Tests for map_error function."""
def test_authentication_error(self):
"""openai.AuthenticationError -> AuthenticationError."""
exc = _make_openai_error(openai.AuthenticationError, status_code=401)
result = map_error(exc)
assert isinstance(result, AuthenticationError)
assert result.status_code == 401
def test_rate_limit_error(self):
"""openai.RateLimitError -> RateLimitError and triggers global block."""
exc = _make_openai_error(openai.RateLimitError, status_code=429)
with patch("providers.common.error_mapping.GlobalRateLimiter") as mock_rl:
mock_instance = MagicMock()
mock_rl.get_instance.return_value = mock_instance
result = map_error(exc)
assert isinstance(result, RateLimitError)
assert result.status_code == 429
mock_instance.set_blocked.assert_called_once_with(60)
def test_bad_request_error(self):
"""openai.BadRequestError -> InvalidRequestError."""
exc = _make_openai_error(openai.BadRequestError, status_code=400)
result = map_error(exc)
assert isinstance(result, InvalidRequestError)
assert result.status_code == 400
@pytest.mark.parametrize(
"message",
["Server overloaded", "No capacity available"],
ids=["overloaded", "capacity"],
)
def test_internal_server_error_overloaded(self, message):
"""InternalServerError with overloaded/capacity keywords -> OverloadedError."""
exc = _make_openai_error(
openai.InternalServerError, message=message, status_code=500
)
result = map_error(exc)
assert isinstance(result, OverloadedError)
assert result.status_code == 529
def test_internal_server_error_generic(self):
"""InternalServerError without keywords -> APIError(500)."""
exc = _make_openai_error(
openai.InternalServerError, message="Unknown error", status_code=500
)
result = map_error(exc)
assert isinstance(result, APIError)
assert result.status_code == 500
def test_generic_api_error(self):
"""openai.APIError -> APIError with original status_code."""
exc = _make_openai_error(
openai.APIError, message="Bad gateway", status_code=502
)
result = map_error(exc)
assert isinstance(result, APIError)
def test_unmapped_exception_passthrough(self):
"""Non-openai exceptions are returned as-is."""
exc = RuntimeError("unexpected")
result = map_error(exc)
assert result is exc
assert isinstance(result, RuntimeError)
def test_value_error_passthrough(self):
"""ValueError passes through unchanged."""
exc = ValueError("bad value")
result = map_error(exc)
assert result is exc
@pytest.mark.parametrize(
"exc_cls,expected_cls",
[
(openai.AuthenticationError, AuthenticationError),
(openai.RateLimitError, RateLimitError),
(openai.BadRequestError, InvalidRequestError),
],
ids=["auth", "rate_limit", "bad_request"],
)
def test_mapping_parametrized(self, exc_cls, expected_cls):
"""Parametrized check of openai -> provider error mapping."""
status_map = {
openai.AuthenticationError: 401,
openai.RateLimitError: 429,
openai.BadRequestError: 400,
}
exc = _make_openai_error(exc_cls, status_code=status_map[exc_cls])
with patch("providers.common.error_mapping.GlobalRateLimiter"):
result = map_error(exc)
assert isinstance(result, expected_cls)