"""Unit tests for retries module.""" import pytest def test_exception_hierarchy(): from libs.common.retries import ( ACEFError, DependencyError, NonRetryableError, RetryableError, ValidationError, ) assert issubclass(RetryableError, ACEFError) assert issubclass(NonRetryableError, ACEFError) assert issubclass(ValidationError, ACEFError) assert issubclass(DependencyError, ACEFError) def test_error_fields(): from libs.common.retries import RetryableError err = RetryableError("msg", source="sec", entity="CIK123", context={"url": "x"}) assert err.source == "sec" assert err.entity == "CIK123" assert err.context["url"] == "x" @pytest.mark.asyncio async def test_with_retry_succeeds_on_first_attempt(): from libs.common.retries import with_retry call_count = 0 @with_retry(max_attempts=3) async def func(): nonlocal call_count call_count += 1 return "ok" result = await func() assert result == "ok" assert call_count == 1 @pytest.mark.asyncio async def test_with_retry_retries_on_retryable_error(): from libs.common.retries import RetryableError, with_retry call_count = 0 @with_retry(max_attempts=3, min_wait=0.01, max_wait=0.1) async def func(): nonlocal call_count call_count += 1 if call_count < 3: raise RetryableError("transient") return "ok" result = await func() assert result == "ok" assert call_count == 3 @pytest.mark.asyncio async def test_with_retry_does_not_retry_non_retryable(): from libs.common.retries import NonRetryableError, with_retry call_count = 0 @with_retry(max_attempts=3, min_wait=0.01, max_wait=0.1) async def func(): nonlocal call_count call_count += 1 raise NonRetryableError("permanent") with pytest.raises(NonRetryableError): await func() assert call_count == 1 @pytest.mark.asyncio async def test_with_retry_exhaustion(): """max_attempts 모두 소진 후 RetryableError가 최종 raise된다.""" from libs.common.retries import RetryableError, with_retry call_count = 0 @with_retry(max_attempts=3, min_wait=0.01, max_wait=0.1) async def func(): nonlocal call_count call_count += 1 raise RetryableError("always fails") with pytest.raises(RetryableError): await func() assert call_count == 3