ForcePilot/backend/test/unit/gateway/protocol/test_errors.py

122 lines
4.0 KiB
Python
Raw Normal View History

from __future__ import annotations
import pytest
from pydantic import ValidationError
from yuxi.gateway.protocol.errors import ErrorCode, ErrorDetail
class TestErrorCode:
def test_invalid_request_value(self):
assert ErrorCode.INVALID_REQUEST == -32600
def test_method_not_found_value(self):
assert ErrorCode.METHOD_NOT_FOUND == -32601
def test_invalid_params_value(self):
assert ErrorCode.INVALID_PARAMS == -32602
def test_internal_error_value(self):
assert ErrorCode.INTERNAL_ERROR == -32603
def test_rate_limited_value(self):
assert ErrorCode.RATE_LIMITED == -32000
def test_auth_required_value(self):
assert ErrorCode.AUTH_REQUIRED == -32001
def test_is_int_enum(self):
assert isinstance(ErrorCode.INVALID_REQUEST, int)
def test_all_values_negative(self):
for code in ErrorCode:
assert code.value < 0
def test_length_is_eleven(self):
assert len(ErrorCode) == 11
def test_not_linked_value(self):
assert ErrorCode.NOT_LINKED == -32002
def test_not_paired_value(self):
assert ErrorCode.NOT_PAIRED == -32003
def test_agent_timeout_value(self):
assert ErrorCode.AGENT_TIMEOUT == -32004
def test_approval_not_found_value(self):
assert ErrorCode.APPROVAL_NOT_FOUND == -32005
def test_unavailable_value(self):
assert ErrorCode.UNAVAILABLE == -32006
class TestErrorDetail:
def test_minimal_construction(self):
detail = ErrorDetail(code=ErrorCode.INTERNAL_ERROR, message="server error")
assert detail.code == ErrorCode.INTERNAL_ERROR
assert detail.message == "server error"
assert detail.details is None
assert detail.retryable is False
assert detail.retry_after_ms is None
def test_full_construction(self):
detail = ErrorDetail(
code=ErrorCode.RATE_LIMITED,
message="rate limited",
details="max 100 req/min",
retryable=True,
retry_after_ms=60000,
)
assert detail.details == "max 100 req/min"
assert detail.retryable is True
assert detail.retry_after_ms == 60000
def test_code_is_required(self):
with pytest.raises(ValidationError):
ErrorDetail(message="error")
def test_message_is_required(self):
with pytest.raises(ValidationError):
ErrorDetail(code=ErrorCode.INTERNAL_ERROR)
def test_defaults(self):
detail = ErrorDetail(code=ErrorCode.METHOD_NOT_FOUND, message="not found")
assert detail.details is None
assert detail.retryable is False
assert detail.retry_after_ms is None
def test_json_serialization(self):
detail = ErrorDetail(code=ErrorCode.AUTH_REQUIRED, message="auth needed", retryable=False)
data = detail.model_dump()
assert data == {
"code": -32001,
"message": "auth needed",
"details": None,
"retryable": False,
"retry_after_ms": None,
}
def test_json_deserialization(self):
data = {
"code": -32600, "message": "invalid json", "details": "bad format",
"retryable": False, "retry_after_ms": None,
}
detail = ErrorDetail.model_validate(data)
assert detail.code == ErrorCode.INVALID_REQUEST
assert detail.message == "invalid json"
assert detail.details == "bad format"
def test_retry_info_for_rate_limit(self):
detail = ErrorDetail(code=ErrorCode.RATE_LIMITED, message="too many", retryable=True, retry_after_ms=30000)
assert detail.retryable is True
assert detail.retry_after_ms == 30000
def test_code_accepts_int_enum(self):
detail = ErrorDetail(code=ErrorCode.INVALID_PARAMS, message="bad params")
assert detail.code == -32602
def test_message_preserved_as_string(self):
detail = ErrorDetail(code=ErrorCode.INTERNAL_ERROR, message="unexpected null")
assert isinstance(detail.message, str)