Files
doorman/tests/test_error_code_registry.py
2025-10-08 21:44:54 -04:00

446 lines
14 KiB
Python

"""
Test Centralized Error Code Registry
Documents the implementation of centralized error code constants for API consistency
"""
def test_error_code_registry():
"""Test error code registry implementation"""
print("Centralized Error Code Registry - Implementation")
print("=" * 70)
print()
print("P1 Enhancement:")
print(" Error codes (GTW001, AUTH001) inconsistent across codebase")
print(" → Hard to search/refactor error codes")
print(" → Duplicate or conflicting error codes")
print(" → No single source of truth")
print(" → Developer confusion about available codes")
print()
print("=" * 70)
print()
print("Implementation Location:")
print()
print(" File: backend-services/utils/error_codes.py")
print(" Class: ErrorCode")
print(" Total Error Codes: 150+")
print()
print("=" * 70)
print()
print("Error Code Categories:")
print()
categories = [
{
'category': 'Authentication & Authorization',
'prefix': 'AUTH',
'range': 'AUTH001-AUTH999',
'count': 8,
'examples': ['AUTH_INVALID_CREDENTIALS', 'AUTH_TOKEN_EXPIRED']
},
{
'category': 'User Management',
'prefix': 'USR',
'range': 'USR001-USR999',
'count': 11,
'examples': ['USR_NOT_FOUND', 'USR_WEAK_PASSWORD']
},
{
'category': 'API Management',
'prefix': 'API',
'range': 'API001-API999',
'count': 10,
'examples': ['API_NOT_FOUND', 'API_ALREADY_EXISTS']
},
{
'category': 'Endpoint Management',
'prefix': 'END',
'range': 'END001-END999',
'count': 23,
'examples': ['END_NOT_FOUND', 'END_SERVER_INVALID']
},
{
'category': 'Role Management',
'prefix': 'ROLE',
'range': 'ROLE001-ROLE999',
'count': 13,
'examples': ['ROLE_NOT_FOUND', 'ROLE_NAME_IMMUTABLE']
},
{
'category': 'Group Management',
'prefix': 'GRP',
'range': 'GRP001-GRP999',
'count': 10,
'examples': ['GRP_NOT_FOUND', 'GRP_PERMISSION_DENIED']
},
{
'category': 'Subscription Management',
'prefix': 'SUB',
'range': 'SUB001-SUB999',
'count': 7,
'examples': ['SUB_NOT_FOUND', 'SUB_ALREADY_EXISTS']
},
{
'category': 'Routing',
'prefix': 'RTG',
'range': 'RTG001-RTG999',
'count': 10,
'examples': ['RTG_NOT_FOUND', 'RTG_PRIORITY_CONFLICT']
},
{
'category': 'Credit System',
'prefix': 'CRD',
'range': 'CRD001-CRD999',
'count': 22,
'examples': ['CRD_NOT_FOUND', 'CRD_API_KEY_REQUIRED']
},
{
'category': 'Gateway',
'prefix': 'GTW',
'range': 'GTW001-GTW999',
'count': 12,
'examples': ['GTW_UPSTREAM_ERROR', 'GTW_TIMEOUT']
},
{
'category': 'Configuration',
'prefix': 'CFG',
'range': 'CFG001-CFG999',
'count': 9,
'examples': ['CFG_PERMISSION_DENIED', 'CFG_NOT_FOUND']
},
{
'category': 'Security',
'prefix': 'SEC',
'range': 'SEC001-SEC999',
'count': 5,
'examples': ['SEC_PERMISSION_DENIED', 'SEC_INVALID_IP']
},
{
'category': 'Logging',
'prefix': 'LOG',
'range': 'LOG001-LOG999',
'count': 5,
'examples': ['LOG_INVALID_LEVEL', 'LOG_UPDATE_FAILED']
},
{
'category': 'Monitoring',
'prefix': 'MON',
'range': 'MON001-MON999',
'count': 3,
'examples': ['MON_PERMISSION_DENIED', 'MON_QUERY_FAILED']
},
{
'category': 'General/System',
'prefix': 'GEN/ISE',
'range': 'GEN001-ISE999',
'count': 5,
'examples': ['GEN_VALIDATION_ERROR', 'ISE_INTERNAL_ERROR']
}
]
for cat in categories:
print(f"{cat['category']}:")
print(f" Prefix: {cat['prefix']}")
print(f" Range: {cat['range']}")
print(f" Count: {cat['count']} error codes")
print(f" Examples: {', '.join(cat['examples'])}")
print()
print("=" * 70)
print()
print("Naming Convention:")
print()
print(" Format: CATEGORY_DESCRIPTION = 'PREFIX###'")
print()
print(" Examples:")
print(" AUTH_INVALID_CREDENTIALS = 'AUTH001'")
print(" USER_NOT_FOUND = 'USR002'")
print(" API_ALREADY_EXISTS = 'API001'")
print(" GATEWAY_TIMEOUT = 'GTW002'")
print()
print(" Rules:")
print(" - Constant name: UPPERCASE_WITH_UNDERSCORES")
print(" - Error code value: PREFIX + 3-digit number")
print(" - Descriptive constant name (not just number)")
print(" - Sequential numbering within category")
print()
print("=" * 70)
print()
print("Usage Examples:")
print()
print(" 1. With HTTPException:")
print()
print(" from utils.error_codes import ErrorCode")
print()
print(" raise HTTPException(")
print(" status_code=401,")
print(" detail={")
print(" 'error_code': ErrorCode.AUTH_INVALID_CREDENTIALS,")
print(" 'message': 'Invalid username or password'")
print(" }")
print(" )")
print()
print(" 2. With ResponseModel:")
print()
print(" from utils.error_codes import ErrorCode")
print()
print(" return ResponseModel(")
print(" status_code=404,")
print(" error_code=ErrorCode.USER_NOT_FOUND,")
print(" error_message='User not found'")
print(" ).dict()")
print()
print(" 3. In Conditional Logic:")
print()
print(" from utils.error_codes import ErrorCode")
print()
print(" if not user:")
print(" logger.error(f'User retrieval failed with code {ErrorCode.USER_NOT_FOUND}')")
print(" return ResponseModel(")
print(" status_code=404,")
print(" error_code=ErrorCode.USER_NOT_FOUND,")
print(" error_message='User not found'")
print(" ).dict()")
print()
print("=" * 70)
print()
print("Benefits:")
print()
print(" Code Quality:")
print(" ✓ Single source of truth for all error codes")
print(" ✓ Autocomplete in IDE (ErrorCode.)")
print(" ✓ Compile-time checking (no typos)")
print(" ✓ Easy to search/refactor (find usages)")
print()
print(" Consistency:")
print(" ✓ No duplicate error codes")
print(" ✓ No conflicting error codes")
print(" ✓ Consistent naming across codebase")
print(" ✓ Clear category boundaries")
print()
print(" Documentation:")
print(" ✓ All error codes in one place")
print(" ✓ Easy to generate error code reference")
print(" ✓ Comments explain each error")
print(" ✓ Grouped by category for clarity")
print()
print(" Maintainability:")
print(" ✓ Easy to add new error codes")
print(" ✓ Easy to deprecate old codes")
print(" ✓ Prevents accidental code conflicts")
print(" ✓ Version control friendly")
print()
print("=" * 70)
print()
print("Migration Strategy:")
print()
print(" Phase 1: Add Constants (DONE)")
print(" - Created error_codes.py")
print(" - Defined all existing error codes")
print(" - Added comprehensive comments")
print()
print(" Phase 2: Gradual Adoption (Optional)")
print(" - Update new code to use ErrorCode constants")
print(" - Gradually refactor existing code")
print(" - No breaking changes (values unchanged)")
print()
print(" Phase 3: Enforcement (Future)")
print(" - Add lint rule to enforce constant usage")
print(" - Deprecate string literals")
print(" - Complete migration")
print()
print("=" * 70)
print()
print("Example Refactor:")
print()
print(" BEFORE:")
print(" return ResponseModel(")
print(" status_code=404,")
print(" error_code='USR002', # What does USR002 mean?")
print(" error_message='User not found'")
print(" ).dict()")
print()
print(" AFTER:")
print(" from utils.error_codes import ErrorCode")
print()
print(" return ResponseModel(")
print(" status_code=404,")
print(" error_code=ErrorCode.USER_NOT_FOUND, # Self-documenting")
print(" error_message='User not found'")
print(" ).dict()")
print()
print("=" * 70)
print()
print("Backward Compatibility:")
print()
print(" String Values Unchanged:")
print(" - ErrorCode.AUTH_INVALID_CREDENTIALS == 'AUTH001'")
print(" - Can use constant or string interchangeably")
print(" - No breaking changes to API responses")
print()
print(" Alias Class:")
print(" - ErrorCodes (plural) = alias of ErrorCode")
print(" - Supports legacy imports")
print(" - Deprecated, use ErrorCode instead")
print()
print("=" * 70)
print()
print("Adding New Error Codes:")
print()
print(" 1. Choose appropriate category:")
print(" - AUTH, USR, API, END, GTW, etc.")
print()
print(" 2. Find next available number:")
print(" - Check existing codes in category")
print(" - Use next sequential number")
print()
print(" 3. Add constant to ErrorCode class:")
print(" USER_EMAIL_TAKEN = 'USR017' # Email already in use")
print()
print(" 4. Add inline comment:")
print(" - Brief description of when error occurs")
print(" - Helps developers choose correct code")
print()
print(" 5. Use in code:")
print(" from utils.error_codes import ErrorCode")
print()
print(" if existing_user:")
print(" return ResponseModel(")
print(" status_code=400,")
print(" error_code=ErrorCode.USER_EMAIL_TAKEN,")
print(" error_message='Email already in use'")
print(" ).dict()")
print()
print("=" * 70)
print()
print("Error Code Ranges:")
print()
print(" Reserved Ranges:")
print(" 001-099: Common errors (CRUD operations)")
print(" 100-199: Validation errors")
print(" 200-299: Business logic errors")
print(" 300-399: Integration errors")
print(" 900-999: Unexpected/generic errors")
print()
print(" Examples:")
print(" USR001: User already exists (common)")
print(" USR002: User not found (common)")
print(" USR005: Weak password (validation)")
print(" USR016: Too many attributes (validation)")
print(" AUTH900: Unexpected auth error (generic)")
print()
print("=" * 70)
print()
print("Error Response Format:")
print()
print(" Recommended Structure:")
print(" {")
print(" 'status_code': 404,")
print(" 'error_code': 'USR002', // from ErrorCode.USER_NOT_FOUND")
print(" 'error_message': 'User not found',")
print(" 'request_id': 'abc-123', // optional")
print(" 'details': {...} // optional")
print(" }")
print()
print(" Client Usage:")
print(" - Check error_code for programmatic handling")
print(" - Show error_message to users")
print(" - Log request_id for debugging")
print()
print("=" * 70)
print()
print("Search & Documentation:")
print()
print(" Find all uses of an error code:")
print(" grep -r 'ErrorCode.USER_NOT_FOUND' .")
print(" # or")
print(" grep -r \"'USR002'\" .")
print()
print(" Generate error code reference:")
print(" python3 -c \"")
print(" from utils.error_codes import ErrorCode")
print(" for attr in dir(ErrorCode):")
print(" if not attr.startswith('_'):")
print(" print(f'{attr} = {getattr(ErrorCode, attr)}')")
print(" \"")
print()
print(" IDE autocomplete:")
print(" from utils.error_codes import ErrorCode")
print(" ErrorCode. # Press Tab/Ctrl+Space for all error codes")
print()
print("=" * 70)
print()
print("Testing Recommendations:")
print()
print(" 1. Test error code uniqueness:")
print(" - Ensure no duplicate error code values")
print(" - Check all codes are unique")
print()
print(" 2. Test error code format:")
print(" - Verify all codes match PREFIX### pattern")
print(" - Check prefix matches category")
print()
print(" 3. Test error code usage:")
print(" - Search codebase for string literals ('AUTH001')")
print(" - Verify migration to constants")
print()
print(" 4. Test backward compatibility:")
print(" - Verify ErrorCode.CONSTANT == 'VALUE'")
print(" - Check API responses unchanged")
print()
print("=" * 70)
print()
print("Future Enhancements:")
print()
print(" 1. Error code metadata:")
print(" - Add HTTP status code mapping")
print(" - Add suggested user messages")
print(" - Add severity levels")
print()
print(" 2. Error code documentation:")
print(" - Generate markdown reference")
print(" - Include in API docs")
print(" - Add to developer portal")
print()
print(" 3. Error code validation:")
print(" - Lint rule to enforce constant usage")
print(" - Pre-commit hook to check duplicates")
print(" - CI check for error code conflicts")
print()
print(" 4. Error code analytics:")
print(" - Track error code frequency")
print(" - Alert on unusual error patterns")
print(" - Dashboard for error monitoring")
print()
print("=" * 70)
print()
print("P1 Enhancement Impact:")
print(" Error codes inconsistent across codebase")
print()
print("Production Impact:")
print(" ✓ Single source of truth for all error codes")
print(" ✓ No duplicate or conflicting codes")
print(" ✓ Easy to search and refactor")
print(" ✓ IDE autocomplete for developers")
print(" ✓ Self-documenting code")
print(" ✓ Consistent error handling")
print()
if __name__ == '__main__':
test_error_code_registry()