- Add documentation warnings for in-memory rate limiting and failed login attempts - Consolidate duplicate health endpoints into api/health.py - Fix CLI to use correct async rescan method names - Update download.py and anime.py to use custom exception classes - Add WebSocket room validation and rate limiting
123 lines
3.6 KiB
Python
123 lines
3.6 KiB
Python
"""Unit tests for health check endpoints."""
|
|
|
|
from unittest.mock import AsyncMock, patch
|
|
|
|
import pytest
|
|
|
|
from src.server.api.health import (
|
|
DatabaseHealth,
|
|
HealthStatus,
|
|
SystemMetrics,
|
|
basic_health_check,
|
|
check_database_health,
|
|
check_filesystem_health,
|
|
get_system_metrics,
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_basic_health_check():
|
|
"""Test basic health check endpoint."""
|
|
with patch("src.config.settings.settings") as mock_settings, \
|
|
patch("src.server.utils.dependencies._series_app", None):
|
|
mock_settings.anime_directory = ""
|
|
result = await basic_health_check()
|
|
|
|
assert isinstance(result, HealthStatus)
|
|
assert result.status == "healthy"
|
|
assert result.version == "1.0.0"
|
|
assert result.service == "aniworld-api"
|
|
assert result.timestamp is not None
|
|
assert result.series_app_initialized is False
|
|
assert result.anime_directory_configured is False
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_database_health_check_success():
|
|
"""Test database health check with successful connection."""
|
|
# Mock database session
|
|
mock_db = AsyncMock()
|
|
mock_db.execute = AsyncMock()
|
|
|
|
result = await check_database_health(mock_db)
|
|
|
|
assert isinstance(result, DatabaseHealth)
|
|
assert result.status == "healthy"
|
|
assert result.connection_time_ms >= 0
|
|
assert "successful" in result.message.lower()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_database_health_check_failure():
|
|
"""Test database health check with failed connection."""
|
|
# Mock database session that raises error
|
|
mock_db = AsyncMock()
|
|
mock_db.execute = AsyncMock(side_effect=Exception("Connection failed"))
|
|
|
|
result = await check_database_health(mock_db)
|
|
|
|
assert isinstance(result, DatabaseHealth)
|
|
assert result.status == "unhealthy"
|
|
assert "failed" in result.message.lower()
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_filesystem_health_check_success():
|
|
"""Test filesystem health check with accessible directories."""
|
|
with patch("os.path.exists", return_value=True), patch(
|
|
"os.access", return_value=True
|
|
):
|
|
result = await check_filesystem_health()
|
|
|
|
assert result["status"] in ["healthy", "degraded"]
|
|
assert "data_dir_writable" in result
|
|
assert "logs_dir_writable" in result
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_filesystem_health_check_failure():
|
|
"""Test filesystem health check with inaccessible directories."""
|
|
with patch("os.path.exists", return_value=False), patch(
|
|
"os.access", return_value=False
|
|
):
|
|
result = await check_filesystem_health()
|
|
|
|
assert "status" in result
|
|
assert "message" in result
|
|
|
|
|
|
def test_get_system_metrics():
|
|
"""Test system metrics collection."""
|
|
result = get_system_metrics()
|
|
|
|
assert isinstance(result, SystemMetrics)
|
|
assert result.cpu_percent >= 0
|
|
assert result.memory_percent >= 0
|
|
assert result.memory_available_mb > 0
|
|
assert result.disk_percent >= 0
|
|
assert result.disk_free_mb > 0
|
|
assert result.uptime_seconds > 0
|
|
|
|
|
|
def test_system_metrics_values_reasonable():
|
|
"""Test that system metrics are within reasonable ranges."""
|
|
result = get_system_metrics()
|
|
|
|
# CPU should be 0-100%
|
|
assert 0 <= result.cpu_percent <= 100
|
|
|
|
# Memory should be 0-100%
|
|
assert 0 <= result.memory_percent <= 100
|
|
|
|
# Disk should be 0-100%
|
|
assert 0 <= result.disk_percent <= 100
|
|
|
|
# Memory available should be positive
|
|
assert result.memory_available_mb > 0
|
|
|
|
# Disk free should be positive
|
|
assert result.disk_free_mb > 0
|
|
|
|
# Uptime should be positive
|
|
assert result.uptime_seconds > 0
|