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