mirror of
https://github.com/aljazceru/enclava.git
synced 2025-12-18 07:54:29 +01:00
603 lines
25 KiB
Python
603 lines
25 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Budget Enforcement Extended Tests - Phase 1 Critical Business Logic
|
|
Priority: app/services/budget_enforcement.py (16% → 85% coverage)
|
|
|
|
Extends existing budget tests with comprehensive coverage:
|
|
- Usage tracking across time periods
|
|
- Budget reset logic
|
|
- Multi-user budget isolation
|
|
- Budget expiration handling
|
|
- Cost calculation accuracy
|
|
- Complex billing scenarios
|
|
"""
|
|
|
|
import pytest
|
|
from datetime import datetime, timedelta
|
|
from decimal import Decimal
|
|
from unittest.mock import Mock, patch, AsyncMock
|
|
from app.services.budget_enforcement import BudgetEnforcementService
|
|
from app.models.budget import Budget
|
|
from app.models.api_key import APIKey
|
|
from app.models.user import User
|
|
|
|
|
|
class TestBudgetEnforcementExtended:
|
|
"""Extended comprehensive test suite for Budget Enforcement Service"""
|
|
|
|
@pytest.fixture
|
|
def budget_service(self):
|
|
"""Create budget enforcement service instance"""
|
|
return BudgetEnforcementService()
|
|
|
|
@pytest.fixture
|
|
def sample_user(self):
|
|
"""Sample user for testing"""
|
|
return User(
|
|
id=1,
|
|
username="testuser",
|
|
email="test@example.com",
|
|
is_active=True
|
|
)
|
|
|
|
@pytest.fixture
|
|
def sample_api_key(self, sample_user):
|
|
"""Sample API key for testing"""
|
|
return APIKey(
|
|
id=1,
|
|
user_id=sample_user.id,
|
|
name="Test API Key",
|
|
key_prefix="ce_test",
|
|
hashed_key="hashed_test_key",
|
|
is_active=True,
|
|
created_at=datetime.utcnow()
|
|
)
|
|
|
|
@pytest.fixture
|
|
def sample_budget(self, sample_api_key):
|
|
"""Sample budget for testing"""
|
|
return Budget(
|
|
id=1,
|
|
api_key_id=sample_api_key.id,
|
|
monthly_limit=Decimal("100.00"),
|
|
current_usage=Decimal("25.50"),
|
|
reset_day=1,
|
|
is_active=True,
|
|
created_at=datetime.utcnow()
|
|
)
|
|
|
|
@pytest.fixture
|
|
def mock_db_session(self):
|
|
"""Mock database session"""
|
|
mock_session = Mock()
|
|
mock_session.query.return_value.filter.return_value.first.return_value = None
|
|
mock_session.add.return_value = None
|
|
mock_session.commit.return_value = None
|
|
return mock_session
|
|
|
|
# === USAGE TRACKING ACROSS TIME PERIODS ===
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_usage_tracking_daily_aggregation(self, budget_service, sample_budget):
|
|
"""Test daily usage aggregation and tracking"""
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
# Mock budget lookup
|
|
mock_session.query.return_value.filter.return_value.first.return_value = sample_budget
|
|
|
|
# Track usage across multiple requests in same day
|
|
daily_usages = [
|
|
{"tokens": 100, "cost": Decimal("0.50")},
|
|
{"tokens": 200, "cost": Decimal("1.00")},
|
|
{"tokens": 150, "cost": Decimal("0.75")}
|
|
]
|
|
|
|
for usage in daily_usages:
|
|
await budget_service.track_usage(
|
|
api_key_id=1,
|
|
tokens=usage["tokens"],
|
|
cost=usage["cost"],
|
|
model="gpt-3.5-turbo"
|
|
)
|
|
|
|
# Verify daily aggregation
|
|
daily_total = await budget_service.get_daily_usage(api_key_id=1, date=datetime.now().date())
|
|
|
|
assert daily_total["total_tokens"] == 450
|
|
assert daily_total["total_cost"] == Decimal("2.25")
|
|
assert daily_total["request_count"] == 3
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_usage_tracking_weekly_aggregation(self, budget_service, sample_budget):
|
|
"""Test weekly usage aggregation"""
|
|
base_date = datetime.now()
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.first.return_value = sample_budget
|
|
|
|
# Track usage across different days of the week
|
|
weekly_usages = [
|
|
{"date": base_date - timedelta(days=0), "cost": Decimal("10.00")},
|
|
{"date": base_date - timedelta(days=1), "cost": Decimal("15.00")},
|
|
{"date": base_date - timedelta(days=2), "cost": Decimal("12.50")},
|
|
{"date": base_date - timedelta(days=6), "cost": Decimal("8.75")}
|
|
]
|
|
|
|
for usage in weekly_usages:
|
|
with patch('datetime.datetime') as mock_datetime:
|
|
mock_datetime.utcnow.return_value = usage["date"]
|
|
|
|
await budget_service.track_usage(
|
|
api_key_id=1,
|
|
tokens=100,
|
|
cost=usage["cost"],
|
|
model="gpt-4"
|
|
)
|
|
|
|
# Get weekly aggregation
|
|
weekly_total = await budget_service.get_weekly_usage(api_key_id=1)
|
|
|
|
assert weekly_total["total_cost"] == Decimal("46.25")
|
|
assert weekly_total["day_count"] == 4
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_usage_tracking_monthly_rollover(self, budget_service, sample_budget):
|
|
"""Test monthly usage tracking with month rollover"""
|
|
current_month = datetime.now().replace(day=1)
|
|
previous_month = (current_month - timedelta(days=1)).replace(day=15)
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.first.return_value = sample_budget
|
|
|
|
# Track usage in previous month
|
|
with patch('datetime.datetime') as mock_datetime:
|
|
mock_datetime.utcnow.return_value = previous_month
|
|
|
|
await budget_service.track_usage(
|
|
api_key_id=1,
|
|
tokens=1000,
|
|
cost=Decimal("20.00"),
|
|
model="gpt-4"
|
|
)
|
|
|
|
# Track usage in current month
|
|
with patch('datetime.datetime') as mock_datetime:
|
|
mock_datetime.utcnow.return_value = current_month
|
|
|
|
await budget_service.track_usage(
|
|
api_key_id=1,
|
|
tokens=500,
|
|
cost=Decimal("10.00"),
|
|
model="gpt-4"
|
|
)
|
|
|
|
# Current month usage should not include previous month
|
|
current_usage = await budget_service.get_current_month_usage(api_key_id=1)
|
|
assert current_usage["total_cost"] == Decimal("10.00")
|
|
|
|
# Previous month should be tracked separately
|
|
previous_usage = await budget_service.get_month_usage(
|
|
api_key_id=1,
|
|
year=previous_month.year,
|
|
month=previous_month.month
|
|
)
|
|
assert previous_usage["total_cost"] == Decimal("20.00")
|
|
|
|
# === BUDGET RESET LOGIC ===
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_reset_monthly(self, budget_service, sample_budget):
|
|
"""Test monthly budget reset functionality"""
|
|
# Budget with reset_day = 1 (first of month)
|
|
sample_budget.reset_day = 1
|
|
sample_budget.current_usage = Decimal("75.00")
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.all.return_value = [sample_budget]
|
|
|
|
# Simulate first of month reset
|
|
await budget_service.reset_monthly_budgets()
|
|
|
|
# Verify budget was reset
|
|
assert sample_budget.current_usage == Decimal("0.00")
|
|
assert sample_budget.last_reset_date.date() == datetime.now().date()
|
|
mock_session.commit.assert_called()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_reset_custom_day(self, budget_service, sample_budget):
|
|
"""Test budget reset on custom day of month"""
|
|
# Budget resets on 15th of month
|
|
sample_budget.reset_day = 15
|
|
sample_budget.current_usage = Decimal("50.00")
|
|
|
|
# Mock current date as 15th
|
|
reset_date = datetime.now().replace(day=15)
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.all.return_value = [sample_budget]
|
|
|
|
with patch('datetime.datetime') as mock_datetime:
|
|
mock_datetime.now.return_value = reset_date
|
|
mock_datetime.utcnow.return_value = reset_date
|
|
|
|
await budget_service.reset_monthly_budgets()
|
|
|
|
# Should reset because it's the 15th
|
|
assert sample_budget.current_usage == Decimal("0.00")
|
|
assert sample_budget.last_reset_date == reset_date
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_no_reset_wrong_day(self, budget_service, sample_budget):
|
|
"""Test that budget doesn't reset on wrong day"""
|
|
# Budget resets on 1st, but current day is 15th
|
|
sample_budget.reset_day = 1
|
|
sample_budget.current_usage = Decimal("50.00")
|
|
original_usage = sample_budget.current_usage
|
|
|
|
current_date = datetime.now().replace(day=15)
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.all.return_value = [sample_budget]
|
|
|
|
with patch('datetime.datetime') as mock_datetime:
|
|
mock_datetime.now.return_value = current_date
|
|
|
|
await budget_service.reset_monthly_budgets()
|
|
|
|
# Should NOT reset
|
|
assert sample_budget.current_usage == original_usage
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_reset_already_done_today(self, budget_service, sample_budget):
|
|
"""Test that budget doesn't reset twice on same day"""
|
|
sample_budget.reset_day = 1
|
|
sample_budget.current_usage = Decimal("25.00")
|
|
sample_budget.last_reset_date = datetime.now() # Already reset today
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.all.return_value = [sample_budget]
|
|
|
|
await budget_service.reset_monthly_budgets()
|
|
|
|
# Should not reset again
|
|
assert sample_budget.current_usage == Decimal("25.00")
|
|
|
|
# === MULTI-USER BUDGET ISOLATION ===
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_isolation_between_users(self, budget_service):
|
|
"""Test that budget usage is isolated between different users"""
|
|
# Create budgets for different users
|
|
user1_budget = Budget(
|
|
id=1, api_key_id=1, monthly_limit=Decimal("100.00"),
|
|
current_usage=Decimal("0.00"), is_active=True
|
|
)
|
|
user2_budget = Budget(
|
|
id=2, api_key_id=2, monthly_limit=Decimal("200.00"),
|
|
current_usage=Decimal("0.00"), is_active=True
|
|
)
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
# Mock different budget lookups for different API keys
|
|
def mock_budget_lookup(*args, **kwargs):
|
|
filter_call = args[0]
|
|
if "api_key_id == 1" in str(filter_call):
|
|
return Mock(first=Mock(return_value=user1_budget))
|
|
elif "api_key_id == 2" in str(filter_call):
|
|
return Mock(first=Mock(return_value=user2_budget))
|
|
return Mock(first=Mock(return_value=None))
|
|
|
|
mock_session.query.return_value.filter = mock_budget_lookup
|
|
|
|
# Track usage for user 1
|
|
await budget_service.track_usage(
|
|
api_key_id=1,
|
|
tokens=500,
|
|
cost=Decimal("10.00"),
|
|
model="gpt-3.5-turbo"
|
|
)
|
|
|
|
# Track usage for user 2
|
|
await budget_service.track_usage(
|
|
api_key_id=2,
|
|
tokens=1000,
|
|
cost=Decimal("25.00"),
|
|
model="gpt-4"
|
|
)
|
|
|
|
# Verify isolation - each user's budget should only reflect their usage
|
|
assert user1_budget.current_usage == Decimal("10.00")
|
|
assert user2_budget.current_usage == Decimal("25.00")
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_check_isolation(self, budget_service):
|
|
"""Test that budget checks are isolated per user"""
|
|
# User 1: within budget
|
|
user1_budget = Budget(
|
|
id=1, api_key_id=1, monthly_limit=Decimal("100.00"),
|
|
current_usage=Decimal("50.00"), is_active=True
|
|
)
|
|
|
|
# User 2: over budget
|
|
user2_budget = Budget(
|
|
id=2, api_key_id=2, monthly_limit=Decimal("100.00"),
|
|
current_usage=Decimal("150.00"), is_active=True
|
|
)
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
def mock_budget_lookup(*args, **kwargs):
|
|
# Simulate different budget lookups
|
|
if hasattr(args[0], 'api_key_id') and args[0].api_key_id == 1:
|
|
return Mock(first=Mock(return_value=user1_budget))
|
|
elif hasattr(args[0], 'api_key_id') and args[0].api_key_id == 2:
|
|
return Mock(first=Mock(return_value=user2_budget))
|
|
return Mock(first=Mock(return_value=None))
|
|
|
|
mock_session.query.return_value.filter = mock_budget_lookup
|
|
|
|
# User 1 should be allowed
|
|
can_proceed_1 = await budget_service.check_budget(api_key_id=1, estimated_cost=Decimal("10.00"))
|
|
assert can_proceed_1 is True
|
|
|
|
# User 2 should be blocked
|
|
can_proceed_2 = await budget_service.check_budget(api_key_id=2, estimated_cost=Decimal("10.00"))
|
|
assert can_proceed_2 is False
|
|
|
|
# === BUDGET EXPIRATION HANDLING ===
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_expired_budget_handling(self, budget_service, sample_budget):
|
|
"""Test handling of expired budgets"""
|
|
# Set budget as expired
|
|
sample_budget.expires_at = datetime.utcnow() - timedelta(days=1)
|
|
sample_budget.is_active = True
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.first.return_value = sample_budget
|
|
|
|
# Should not allow usage on expired budget
|
|
can_proceed = await budget_service.check_budget(
|
|
api_key_id=1,
|
|
estimated_cost=Decimal("1.00")
|
|
)
|
|
|
|
assert can_proceed is False
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_auto_deactivation_on_expiry(self, budget_service, sample_budget):
|
|
"""Test automatic budget deactivation when expired"""
|
|
sample_budget.expires_at = datetime.utcnow() - timedelta(hours=1)
|
|
sample_budget.is_active = True
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.all.return_value = [sample_budget]
|
|
|
|
# Run expired budget cleanup
|
|
await budget_service.deactivate_expired_budgets()
|
|
|
|
# Budget should be deactivated
|
|
assert sample_budget.is_active is False
|
|
mock_session.commit.assert_called()
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_grace_period(self, budget_service, sample_budget):
|
|
"""Test budget grace period handling"""
|
|
# Budget expired 30 minutes ago, but has 1-hour grace period
|
|
sample_budget.expires_at = datetime.utcnow() - timedelta(minutes=30)
|
|
sample_budget.grace_period_hours = 1
|
|
sample_budget.is_active = True
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.first.return_value = sample_budget
|
|
|
|
# Should still allow usage during grace period
|
|
can_proceed = await budget_service.check_budget(
|
|
api_key_id=1,
|
|
estimated_cost=Decimal("1.00")
|
|
)
|
|
|
|
assert can_proceed is True
|
|
|
|
# === COST CALCULATION ACCURACY ===
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_token_based_cost_calculation(self, budget_service):
|
|
"""Test accurate token-based cost calculations"""
|
|
test_cases = [
|
|
# (model, input_tokens, output_tokens, expected_cost)
|
|
("gpt-3.5-turbo", 1000, 500, Decimal("0.0020")), # $0.001/1K input, $0.002/1K output
|
|
("gpt-4", 1000, 500, Decimal("0.0450")), # $0.030/1K input, $0.060/1K output
|
|
("text-embedding-ada-002", 1000, 0, Decimal("0.0001")), # $0.0001/1K tokens
|
|
]
|
|
|
|
for model, input_tokens, output_tokens, expected_cost in test_cases:
|
|
calculated_cost = await budget_service.calculate_cost(
|
|
model=model,
|
|
input_tokens=input_tokens,
|
|
output_tokens=output_tokens
|
|
)
|
|
|
|
# Allow small floating point differences
|
|
assert abs(calculated_cost - expected_cost) < Decimal("0.0001")
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_bulk_discount_calculation(self, budget_service):
|
|
"""Test bulk usage discounts"""
|
|
# Simulate high-volume usage (>1M tokens) with discount
|
|
high_volume_tokens = 1500000 # 1.5M tokens
|
|
|
|
# Mock user with bulk pricing tier
|
|
with patch.object(budget_service, '_get_user_pricing_tier') as mock_tier:
|
|
mock_tier.return_value = "enterprise" # 20% discount
|
|
|
|
base_cost = await budget_service.calculate_cost(
|
|
model="gpt-3.5-turbo",
|
|
input_tokens=high_volume_tokens,
|
|
output_tokens=0
|
|
)
|
|
|
|
discounted_cost = await budget_service.apply_volume_discount(
|
|
cost=base_cost,
|
|
monthly_volume=high_volume_tokens
|
|
)
|
|
|
|
# Should apply enterprise discount
|
|
expected_discount = base_cost * Decimal("0.20")
|
|
assert abs(discounted_cost - (base_cost - expected_discount)) < Decimal("0.01")
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_model_specific_pricing(self, budget_service):
|
|
"""Test accurate pricing for different model tiers"""
|
|
models_pricing = {
|
|
"gpt-3.5-turbo": {"input": Decimal("0.001"), "output": Decimal("0.002")},
|
|
"gpt-4": {"input": Decimal("0.030"), "output": Decimal("0.060")},
|
|
"gpt-4-32k": {"input": Decimal("0.060"), "output": Decimal("0.120")},
|
|
"claude-3-sonnet": {"input": Decimal("0.003"), "output": Decimal("0.015")},
|
|
}
|
|
|
|
for model, pricing in models_pricing.items():
|
|
cost = await budget_service.calculate_cost(
|
|
model=model,
|
|
input_tokens=1000,
|
|
output_tokens=500
|
|
)
|
|
|
|
expected_cost = (pricing["input"] * 1) + (pricing["output"] * 0.5)
|
|
assert abs(cost - expected_cost) < Decimal("0.0001")
|
|
|
|
# === COMPLEX BILLING SCENARIOS ===
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_prorated_budget_mid_month(self, budget_service):
|
|
"""Test prorated budget calculations when created mid-month"""
|
|
# Budget created on 15th of 30-day month
|
|
creation_date = datetime.now().replace(day=15)
|
|
monthly_limit = Decimal("100.00")
|
|
|
|
with patch('datetime.datetime') as mock_datetime:
|
|
mock_datetime.now.return_value = creation_date
|
|
|
|
prorated_limit = await budget_service.calculate_prorated_limit(
|
|
monthly_limit=monthly_limit,
|
|
creation_date=creation_date,
|
|
reset_day=1
|
|
)
|
|
|
|
# Should be approximately half the monthly limit (15 days remaining)
|
|
days_remaining = 16 # 15th to end of month
|
|
expected_proration = monthly_limit * (days_remaining / 30)
|
|
|
|
assert abs(prorated_limit - expected_proration) < Decimal("1.00")
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_overage_tracking(self, budget_service, sample_budget):
|
|
"""Test tracking of budget overages"""
|
|
sample_budget.monthly_limit = Decimal("100.00")
|
|
sample_budget.current_usage = Decimal("90.00")
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.first.return_value = sample_budget
|
|
|
|
# Track usage that puts us over budget
|
|
overage_cost = Decimal("25.00")
|
|
|
|
await budget_service.track_usage(
|
|
api_key_id=1,
|
|
tokens=2500,
|
|
cost=overage_cost,
|
|
model="gpt-4"
|
|
)
|
|
|
|
# Verify overage is tracked
|
|
overage_amount = await budget_service.get_current_overage(api_key_id=1)
|
|
assert overage_amount == Decimal("15.00") # $115 - $100 limit
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_soft_vs_hard_limits(self, budget_service, sample_budget):
|
|
"""Test soft limits (warnings) vs hard limits (blocks)"""
|
|
sample_budget.monthly_limit = Decimal("100.00")
|
|
sample_budget.soft_limit_percentage = 80 # Warning at 80%
|
|
sample_budget.current_usage = Decimal("85.00") # Over soft limit
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.first.return_value = sample_budget
|
|
|
|
# Check budget status
|
|
budget_status = await budget_service.get_budget_status(api_key_id=1)
|
|
|
|
assert budget_status["is_over_soft_limit"] is True
|
|
assert budget_status["is_over_hard_limit"] is False
|
|
assert budget_status["soft_limit_threshold"] == Decimal("80.00")
|
|
|
|
# Should still allow usage but with warning
|
|
can_proceed = await budget_service.check_budget(
|
|
api_key_id=1,
|
|
estimated_cost=Decimal("5.00")
|
|
)
|
|
assert can_proceed is True
|
|
assert budget_status["warning_issued"] is True
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_budget_rollover_unused_amount(self, budget_service, sample_budget):
|
|
"""Test rolling over unused budget to next month"""
|
|
sample_budget.monthly_limit = Decimal("100.00")
|
|
sample_budget.current_usage = Decimal("60.00")
|
|
sample_budget.allow_rollover = True
|
|
sample_budget.max_rollover_percentage = 50 # Can rollover up to 50%
|
|
|
|
with patch.object(budget_service, 'db_session', return_value=Mock()) as mock_session:
|
|
mock_session.query.return_value.filter.return_value.all.return_value = [sample_budget]
|
|
|
|
# Process month-end rollover
|
|
await budget_service.process_monthly_rollover()
|
|
|
|
# Calculate expected rollover (40% of unused, capped at 50% of limit)
|
|
unused_amount = Decimal("40.00") # $100 - $60
|
|
max_rollover = sample_budget.monthly_limit * Decimal("0.50") # $50
|
|
expected_rollover = min(unused_amount, max_rollover)
|
|
|
|
# Verify rollover was applied
|
|
assert sample_budget.rollover_credit == expected_rollover
|
|
assert sample_budget.current_usage == Decimal("0.00") # Reset for new month
|
|
|
|
|
|
"""
|
|
COVERAGE ANALYSIS FOR BUDGET ENFORCEMENT:
|
|
|
|
✅ Usage Tracking (3+ tests):
|
|
- Daily/weekly/monthly aggregation
|
|
- Time period rollover handling
|
|
- Cross-period usage isolation
|
|
|
|
✅ Budget Reset Logic (4+ tests):
|
|
- Monthly reset on specified day
|
|
- Custom reset day handling
|
|
- Duplicate reset prevention
|
|
- Reset timing validation
|
|
|
|
✅ Multi-User Isolation (2+ tests):
|
|
- Budget separation between users
|
|
- Independent budget checking
|
|
- Usage tracking isolation
|
|
|
|
✅ Budget Expiration (3+ tests):
|
|
- Expired budget handling
|
|
- Automatic deactivation
|
|
- Grace period support
|
|
|
|
✅ Cost Calculation (3+ tests):
|
|
- Token-based pricing accuracy
|
|
- Model-specific pricing
|
|
- Volume discount application
|
|
|
|
✅ Complex Billing (5+ tests):
|
|
- Prorated budget creation
|
|
- Overage tracking
|
|
- Soft vs hard limits
|
|
- Budget rollover handling
|
|
|
|
ESTIMATED COVERAGE IMPROVEMENT:
|
|
- Current: 16% → Target: 85%
|
|
- Test Count: 20+ comprehensive tests
|
|
- Business Impact: Critical (financial accuracy)
|
|
- Implementation: Cost control and billing validation
|
|
""" |