Files
xiaoxia-saas/tests/unit/test_quota.py
T
Xiaoxia AI b79d6718d6
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 21s
Deploy / Deploy Production (push) Has been cancelled
Deploy / Deploy Staging (push) Has been cancelled
style: normalize python formatting gates
2026-06-21 06:52:19 +08:00

287 lines
8.6 KiB
Python

"""
配额检查服务测试
"""
from unittest.mock import Mock
import pytest
from packages.domain.entities import Workspace
from packages.domain.quota import QuotaChecker, QuotaWarningLevel, get_warning_level
class TestQuotaChecker:
"""配额检查器测试"""
@pytest.fixture
def mock_workspace_repo(self):
repo = Mock()
repo.find_by_id = Mock(return_value=None)
repo.save = Mock()
return repo
@pytest.fixture
def mock_project_repo(self):
repo = Mock()
repo.count_by_workspace = Mock(return_value=0)
return repo
@pytest.fixture
def checker(self, mock_workspace_repo, mock_project_repo):
return QuotaChecker(
workspace_repository=mock_workspace_repo,
project_repository=mock_project_repo,
)
def test_check_can_create_project_within_limit(
self,
checker,
mock_workspace_repo,
mock_project_repo,
):
"""测试在配额内可以创建项目"""
workspace = Workspace(
id="workspace-123",
name="Test",
owner_user_id="owner-id",
subscription_plan="free",
max_projects=3,
)
mock_workspace_repo.find_by_id.return_value = workspace
mock_project_repo.count_by_workspace.return_value = 2
can_create, error = checker.check_can_create_project("workspace-123")
assert can_create is True
assert error is None
def test_check_can_create_project_at_limit(
self,
checker,
mock_workspace_repo,
mock_project_repo,
):
"""测试达到配额限制"""
workspace = Workspace(
id="workspace-123",
name="Test",
owner_user_id="owner-id",
subscription_plan="free",
max_projects=3,
)
mock_workspace_repo.find_by_id.return_value = workspace
mock_project_repo.count_by_workspace.return_value = 3
can_create, error = checker.check_can_create_project("workspace-123")
assert can_create is False
assert "Project limit reached" in error
def test_check_can_create_project_unlimited(
self,
checker,
mock_workspace_repo,
mock_project_repo,
):
"""测试无限制计划"""
workspace = Workspace(
id="workspace-123",
name="Test",
owner_user_id="owner-id",
subscription_plan="pro",
max_projects=999999,
)
mock_workspace_repo.find_by_id.return_value = workspace
mock_project_repo.count_by_workspace.return_value = 1000
can_create, error = checker.check_can_create_project("workspace-123")
assert can_create is True
assert error is None
def test_check_storage_available_within_limit(
self,
checker,
mock_workspace_repo,
):
"""测试存储在配额内"""
workspace = Workspace(
id="workspace-123",
name="Test",
owner_user_id="owner-id",
subscription_plan="free",
max_storage_gb=10,
used_storage_gb=5.0,
)
mock_workspace_repo.find_by_id.return_value = workspace
can_store, error = checker.check_storage_available("workspace-123", 3.0)
assert can_store is True
assert error is None
def test_check_storage_available_exceeded(
self,
checker,
mock_workspace_repo,
):
"""测试存储超出配额"""
workspace = Workspace(
id="workspace-123",
name="Test",
owner_user_id="owner-id",
subscription_plan="free",
max_storage_gb=10,
used_storage_gb=8.0,
)
mock_workspace_repo.find_by_id.return_value = workspace
can_store, error = checker.check_storage_available("workspace-123", 3.0)
assert can_store is False
assert "Storage limit exceeded" in error
def test_get_quota_status(
self,
checker,
mock_workspace_repo,
mock_project_repo,
):
"""测试获取配额状态"""
workspace = Workspace(
id="workspace-123",
name="Test",
owner_user_id="owner-id",
subscription_plan="free",
max_projects=3,
max_storage_gb=10,
used_storage_gb=7.5,
)
mock_workspace_repo.find_by_id.return_value = workspace
mock_project_repo.count_by_workspace.return_value = 2
status = checker.get_quota_status("workspace-123")
assert status is not None
assert status["workspace_id"] == "workspace-123"
assert status["subscription_plan"] == "free"
assert status["projects"]["used"] == 2
assert status["projects"]["limit"] == 3
assert status["projects"]["usage_percent"] == pytest.approx(66.67, rel=0.1)
assert status["storage"]["used_gb"] == 7.5
assert status["storage"]["limit_gb"] == 10
assert status["storage"]["remaining_gb"] == 2.5
assert status["storage"]["usage_percent"] == 75.0
def test_get_quota_status_unlimited(
self,
checker,
mock_workspace_repo,
mock_project_repo,
):
"""测试无限制配额状态"""
workspace = Workspace(
id="workspace-123",
name="Test",
owner_user_id="owner-id",
subscription_plan="pro",
max_projects=999999,
max_storage_gb=100,
used_storage_gb=50.0,
)
mock_workspace_repo.find_by_id.return_value = workspace
mock_project_repo.count_by_workspace.return_value = 1000
status = checker.get_quota_status("workspace-123")
assert status["projects"]["unlimited"] is True
assert status["projects"]["usage_percent"] == 0
def test_update_storage_usage_increase(
self,
checker,
mock_workspace_repo,
):
"""测试增加存储使用量"""
workspace = Workspace(
id="workspace-123",
name="Test",
owner_user_id="owner-id",
max_storage_gb=10,
used_storage_gb=5.0,
)
mock_workspace_repo.find_by_id.return_value = workspace
success, error = checker.update_storage_usage("workspace-123", 2.5)
assert success is True
assert error is None
assert workspace.used_storage_gb == 7.5
mock_workspace_repo.save.assert_called_once()
def test_update_storage_usage_decrease(
self,
checker,
mock_workspace_repo,
):
"""测试减少存储使用量"""
workspace = Workspace(
id="workspace-123",
name="Test",
owner_user_id="owner-id",
max_storage_gb=10,
used_storage_gb=5.0,
)
mock_workspace_repo.find_by_id.return_value = workspace
success, error = checker.update_storage_usage("workspace-123", -2.0)
assert success is True
assert workspace.used_storage_gb == 3.0
def test_update_storage_usage_prevent_negative(
self,
checker,
mock_workspace_repo,
):
"""测试防止负数存储"""
workspace = Workspace(
id="workspace-123",
name="Test",
owner_user_id="owner-id",
max_storage_gb=10,
used_storage_gb=2.0,
)
mock_workspace_repo.find_by_id.return_value = workspace
success, error = checker.update_storage_usage("workspace-123", -5.0)
assert success is True
assert workspace.used_storage_gb == 0.0
class TestWarningLevel:
"""警告级别测试"""
def test_get_warning_level_normal(self):
"""测试正常级别"""
assert get_warning_level(50.0) == QuotaWarningLevel.NORMAL
assert get_warning_level(79.9) == QuotaWarningLevel.NORMAL
def test_get_warning_level_warning(self):
"""测试警告级别"""
assert get_warning_level(80.0) == QuotaWarningLevel.WARNING
assert get_warning_level(85.0) == QuotaWarningLevel.WARNING
assert get_warning_level(89.9) == QuotaWarningLevel.WARNING
def test_get_warning_level_critical(self):
"""测试严重级别"""
assert get_warning_level(90.0) == QuotaWarningLevel.CRITICAL
assert get_warning_level(95.0) == QuotaWarningLevel.CRITICAL
assert get_warning_level(99.9) == QuotaWarningLevel.CRITICAL
def test_get_warning_level_exceeded(self):
"""测试超出级别"""
assert get_warning_level(100.0) == QuotaWarningLevel.EXCEEDED
assert get_warning_level(105.0) == QuotaWarningLevel.EXCEEDED