333 lines
12 KiB
Python
333 lines
12 KiB
Python
import pytest
|
||
from app.services.quota_service import (
|
||
QuotaService,
|
||
QuotaUsage,
|
||
QuotaWarning,
|
||
QuotaType,
|
||
QUOTA_LIMITS,
|
||
WARNING_THRESHOLDS,
|
||
)
|
||
|
||
|
||
class TestQuotaUsage:
|
||
"""额度使用数据结构测试"""
|
||
|
||
def test_quota_usage_creation(self):
|
||
"""测试QuotaUsage数据创建"""
|
||
usage = QuotaUsage(
|
||
quota_type="api_calls",
|
||
used=800,
|
||
limit=1000,
|
||
usage_percentage=80.0,
|
||
status="warning",
|
||
remaining=200,
|
||
)
|
||
assert usage.quota_type == "api_calls"
|
||
assert usage.used == 800
|
||
assert usage.limit == 1000
|
||
assert usage.usage_percentage == 80.0
|
||
assert usage.status == "warning"
|
||
assert usage.remaining == 200
|
||
|
||
def test_quota_usage_unlimited(self):
|
||
"""测试无限额度QuotaUsage"""
|
||
usage = QuotaUsage(
|
||
quota_type="api_calls",
|
||
used=5000,
|
||
limit=-1,
|
||
usage_percentage=0.0,
|
||
status="unlimited",
|
||
remaining=-1,
|
||
)
|
||
assert usage.limit == -1
|
||
assert usage.status == "unlimited"
|
||
assert usage.remaining == -1
|
||
|
||
|
||
class TestQuotaWarning:
|
||
"""预警数据结构测试"""
|
||
|
||
def test_quota_warning_creation(self):
|
||
"""测试QuotaWarning数据创建"""
|
||
warning = QuotaWarning(
|
||
quota_type="api_calls",
|
||
status="warning",
|
||
usage_percentage=80.0,
|
||
message="API调用额度已使用80%",
|
||
recommended_action="请关注使用情况,考虑升级套餐",
|
||
)
|
||
assert warning.quota_type == "api_calls"
|
||
assert warning.status == "warning"
|
||
assert warning.usage_percentage == 80.0
|
||
assert "80%" in warning.message
|
||
|
||
|
||
class TestQuotaService:
|
||
"""额度预警服务测试"""
|
||
|
||
@pytest.fixture
|
||
def quota_service(self):
|
||
"""创建额度服务实例"""
|
||
return QuotaService()
|
||
|
||
def test_calculate_usage_percentage_basic(self, quota_service):
|
||
"""测试基础使用率计算"""
|
||
percentage = quota_service.calculate_usage_percentage(used=800, limit=1000)
|
||
assert percentage == 80.0
|
||
|
||
def test_calculate_usage_percentage_zero(self, quota_service):
|
||
"""测试0%使用率"""
|
||
percentage = quota_service.calculate_usage_percentage(used=0, limit=1000)
|
||
assert percentage == 0.0
|
||
|
||
def test_calculate_usage_percentage_full(self, quota_service):
|
||
"""测试100%使用率"""
|
||
percentage = quota_service.calculate_usage_percentage(used=1000, limit=1000)
|
||
assert percentage == 100.0
|
||
|
||
def test_calculate_usage_percentage_half(self, quota_service):
|
||
"""测试50%使用率"""
|
||
percentage = quota_service.calculate_usage_percentage(used=500, limit=1000)
|
||
assert percentage == 50.0
|
||
|
||
def test_calculate_usage_percentage_unlimited(self, quota_service):
|
||
"""测试无限额度使用率"""
|
||
percentage = quota_service.calculate_usage_percentage(used=5000, limit=-1)
|
||
assert percentage == 0.0
|
||
|
||
def test_get_quota_status_ok(self, quota_service):
|
||
"""测试正常状态(低于80%)"""
|
||
status = quota_service.get_quota_status(usage_percentage=50.0)
|
||
assert status == "ok"
|
||
|
||
def test_get_quota_status_warning(self, quota_service):
|
||
"""测试警告状态(80%)"""
|
||
status = quota_service.get_quota_status(usage_percentage=80.0)
|
||
assert status == "warning"
|
||
|
||
def test_get_quota_status_critical(self, quota_service):
|
||
"""测试严重状态(90%)"""
|
||
status = quota_service.get_quota_status(usage_percentage=90.0)
|
||
assert status == "critical"
|
||
|
||
def test_get_quota_status_exhausted(self, quota_service):
|
||
"""测试耗尽状态(100%)"""
|
||
status = quota_service.get_quota_status(usage_percentage=100.0)
|
||
assert status == "exhausted"
|
||
|
||
def test_get_quota_status_unlimited(self, quota_service):
|
||
"""测试无限状态"""
|
||
status = quota_service.get_quota_status(usage_percentage=0.0, limit=-1)
|
||
assert status == "unlimited"
|
||
|
||
def test_get_quota_limit_free_plan(self, quota_service):
|
||
"""测试免费套餐额度"""
|
||
limit = quota_service.get_quota_limit("free", QuotaType.API_CALLS)
|
||
assert limit == 1000
|
||
|
||
def test_get_quota_limit_basic_plan(self, quota_service):
|
||
"""测试基础套餐额度"""
|
||
limit = quota_service.get_quota_limit("basic", QuotaType.QUERIES)
|
||
assert limit == 500
|
||
|
||
def test_get_quota_limit_pro_plan(self, quota_service):
|
||
"""测试专业套餐额度"""
|
||
limit = quota_service.get_quota_limit("pro", QuotaType.CONTENT_GENERATION)
|
||
assert limit == 1000
|
||
|
||
def test_get_quota_limit_unlimited_plan(self, quota_service):
|
||
"""测试无限套餐额度"""
|
||
limit = quota_service.get_quota_limit("unlimited", QuotaType.API_CALLS)
|
||
assert limit == -1
|
||
|
||
def test_get_remaining_quota(self, quota_service):
|
||
"""测试剩余额度计算"""
|
||
remaining = quota_service.get_remaining(used=800, limit=1000)
|
||
assert remaining == 200
|
||
|
||
def test_get_remaining_quota_exhausted(self, quota_service):
|
||
"""测试额度耗尽"""
|
||
remaining = quota_service.get_remaining(used=1000, limit=1000)
|
||
assert remaining == 0
|
||
|
||
def test_get_remaining_quota_unlimited(self, quota_service):
|
||
"""测试无限额度"""
|
||
remaining = quota_service.get_remaining(used=5000, limit=-1)
|
||
assert remaining == -1
|
||
|
||
def test_get_remaining_quota_overuse(self, quota_service):
|
||
"""测试超额使用"""
|
||
remaining = quota_service.get_remaining(used=1200, limit=1000)
|
||
assert remaining == -200
|
||
|
||
def test_generate_warning_message_warning(self, quota_service):
|
||
"""测试生成警告消息"""
|
||
warning = quota_service.generate_warning(
|
||
quota_type=QuotaType.API_CALLS,
|
||
status="warning",
|
||
usage_percentage=80.0,
|
||
)
|
||
assert warning.quota_type == QuotaType.API_CALLS
|
||
assert warning.status == "warning"
|
||
assert warning.usage_percentage == 80.0
|
||
assert "80%" in warning.message
|
||
assert warning.recommended_action != ""
|
||
|
||
def test_generate_warning_message_critical(self, quota_service):
|
||
"""测试生成严重警告消息"""
|
||
warning = quota_service.generate_warning(
|
||
quota_type=QuotaType.QUERIES,
|
||
status="critical",
|
||
usage_percentage=90.0,
|
||
)
|
||
assert warning.status == "critical"
|
||
assert "90%" in warning.message
|
||
|
||
def test_generate_warning_message_exhausted(self, quota_service):
|
||
"""测试生成耗尽警告消息"""
|
||
warning = quota_service.generate_warning(
|
||
quota_type=QuotaType.CONTENT_GENERATION,
|
||
status="exhausted",
|
||
usage_percentage=100.0,
|
||
)
|
||
assert warning.status == "exhausted"
|
||
assert "100%" in warning.message
|
||
|
||
def test_check_quota_free_plan(self, quota_service):
|
||
"""测试检查免费套餐额度"""
|
||
usage = quota_service.check_quota(
|
||
plan="free",
|
||
quota_type=QuotaType.API_CALLS,
|
||
used=800,
|
||
)
|
||
assert usage.quota_type == QuotaType.API_CALLS
|
||
assert usage.limit == 1000
|
||
assert usage.used == 800
|
||
assert usage.remaining == 200
|
||
assert usage.usage_percentage == 80.0
|
||
assert usage.status == "warning"
|
||
|
||
def test_check_quota_pro_plan_warning(self, quota_service):
|
||
"""测试专业套餐警告状态"""
|
||
usage = quota_service.check_quota(
|
||
plan="pro",
|
||
quota_type=QuotaType.QUERIES,
|
||
used=4500,
|
||
)
|
||
assert usage.limit == 5000
|
||
assert usage.usage_percentage == 90.0
|
||
assert usage.status == "critical"
|
||
|
||
def test_check_quota_unlimited_plan(self, quota_service):
|
||
"""测试无限套餐"""
|
||
usage = quota_service.check_quota(
|
||
plan="unlimited",
|
||
quota_type=QuotaType.API_CALLS,
|
||
used=100000,
|
||
)
|
||
assert usage.limit == -1
|
||
assert usage.status == "unlimited"
|
||
assert usage.usage_percentage == 0.0
|
||
assert usage.remaining == -1
|
||
|
||
def test_check_quota_exhausted(self, quota_service):
|
||
"""测试额度耗尽"""
|
||
usage = quota_service.check_quota(
|
||
plan="free",
|
||
quota_type=QuotaType.QUERIES,
|
||
used=50,
|
||
)
|
||
assert usage.limit == 50
|
||
assert usage.used == 50
|
||
assert usage.remaining == 0
|
||
assert usage.usage_percentage == 100.0
|
||
assert usage.status == "exhausted"
|
||
|
||
def test_check_quota_ok(self, quota_service):
|
||
"""测试额度正常"""
|
||
usage = quota_service.check_quota(
|
||
plan="basic",
|
||
quota_type=QuotaType.STORAGE,
|
||
used=500,
|
||
)
|
||
assert usage.limit == 1000
|
||
assert usage.usage_percentage == 50.0
|
||
assert usage.status == "ok"
|
||
|
||
def test_reset_quota_usage(self, quota_service):
|
||
"""测试额度重置"""
|
||
usage = quota_service.check_quota(
|
||
plan="free",
|
||
quota_type=QuotaType.API_CALLS,
|
||
used=800,
|
||
)
|
||
assert usage.used == 800
|
||
|
||
reset_usage = quota_service.reset_quota(used=800)
|
||
assert reset_usage == 0
|
||
|
||
def test_reset_quota_to_specific_value(self, quota_service):
|
||
"""测试重置到特定值"""
|
||
reset_usage = quota_service.reset_quota(used=500, reset_to=100)
|
||
assert reset_usage == 100
|
||
|
||
def test_get_all_quota_usage(self, quota_service):
|
||
"""测试获取所有额度使用情况"""
|
||
all_usage = quota_service.get_all_quota_usage(
|
||
plan="free",
|
||
api_calls_used=800,
|
||
queries_used=40,
|
||
content_generation_used=8,
|
||
storage_used=50,
|
||
)
|
||
assert len(all_usage) == 4
|
||
assert any(u.quota_type == QuotaType.API_CALLS and u.used == 800 for u in all_usage)
|
||
assert any(u.quota_type == QuotaType.QUERIES and u.used == 40 for u in all_usage)
|
||
|
||
def test_get_warnings_from_usage(self, quota_service):
|
||
"""测试从使用情况生成预警"""
|
||
all_usage = quota_service.get_all_quota_usage(
|
||
plan="free",
|
||
api_calls_used=800,
|
||
queries_used=45,
|
||
content_generation_used=5,
|
||
storage_used=20,
|
||
)
|
||
warnings = quota_service.get_warnings(all_usage)
|
||
assert len(warnings) >= 1
|
||
assert any(w.status in ["warning", "critical", "exhausted"] for w in warnings)
|
||
|
||
def test_boundary_value_0_percent(self, quota_service):
|
||
"""测试边界值0%"""
|
||
usage = quota_service.check_quota(
|
||
plan="free",
|
||
quota_type=QuotaType.API_CALLS,
|
||
used=0,
|
||
)
|
||
assert usage.usage_percentage == 0.0
|
||
assert usage.status == "ok"
|
||
|
||
def test_boundary_value_100_percent(self, quota_service):
|
||
"""测试边界值100%"""
|
||
usage = quota_service.check_quota(
|
||
plan="free",
|
||
quota_type=QuotaType.API_CALLS,
|
||
used=1000,
|
||
)
|
||
assert usage.usage_percentage == 100.0
|
||
assert usage.status == "exhausted"
|
||
|
||
def test_warning_thresholds_constants(self):
|
||
"""测试预警阈值常量"""
|
||
assert WARNING_THRESHOLDS["warning"] == 0.80
|
||
assert WARNING_THRESHOLDS["critical"] == 0.90
|
||
assert WARNING_THRESHOLDS["exhausted"] == 1.00
|
||
|
||
def test_quota_limits_constants(self):
|
||
"""测试套餐额度常量"""
|
||
assert QUOTA_LIMITS["free"]["api_calls"] == 1000
|
||
assert QUOTA_LIMITS["free"]["queries"] == 50
|
||
assert QUOTA_LIMITS["basic"]["api_calls"] == 10000
|
||
assert QUOTA_LIMITS["pro"]["api_calls"] == 100000
|
||
assert QUOTA_LIMITS["unlimited"]["api_calls"] == -1
|