"""Tests for Budget and BudgetStatus."""
from __future__ import annotations
import pytest
from aleph.types import Budget, BudgetStatus
class TestBudgetExceeds:
"""Tests for BudgetStatus.exceeds() checks."""
def test_tokens_exceeded(self) -> None:
budget = Budget(max_tokens=100)
status = BudgetStatus(tokens_used=150)
exceeded, reason = status.exceeds(budget)
assert exceeded is True
assert reason is not None
assert "Token" in reason
def test_tokens_not_exceeded(self) -> None:
budget = Budget(max_tokens=100)
status = BudgetStatus(tokens_used=50)
exceeded, reason = status.exceeds(budget)
assert exceeded is False
assert reason is None
def test_tokens_at_limit(self) -> None:
budget = Budget(max_tokens=100)
status = BudgetStatus(tokens_used=100)
exceeded, reason = status.exceeds(budget)
# At limit, not exceeded
assert exceeded is False
def test_cost_exceeded(self) -> None:
budget = Budget(max_cost_usd=1.0)
status = BudgetStatus(cost_used=1.5)
exceeded, reason = status.exceeds(budget)
assert exceeded is True
assert reason is not None
assert "Cost" in reason
def test_cost_not_exceeded(self) -> None:
budget = Budget(max_cost_usd=1.0)
status = BudgetStatus(cost_used=0.5)
exceeded, reason = status.exceeds(budget)
assert exceeded is False
def test_iterations_exceeded(self) -> None:
budget = Budget(max_iterations=10)
status = BudgetStatus(iterations_used=15)
exceeded, reason = status.exceeds(budget)
assert exceeded is True
assert "Iteration" in reason
def test_depth_exceeded(self) -> None:
budget = Budget(max_depth=2)
status = BudgetStatus(depth_current=3)
exceeded, reason = status.exceeds(budget)
assert exceeded is True
assert "Depth" in reason
def test_wall_time_exceeded(self) -> None:
budget = Budget(max_wall_time_seconds=60.0)
status = BudgetStatus(wall_time_used=120.0)
exceeded, reason = status.exceeds(budget)
assert exceeded is True
assert "Wall-time" in reason
def test_sub_queries_exceeded(self) -> None:
budget = Budget(max_sub_queries=10)
status = BudgetStatus(sub_queries_used=15)
exceeded, reason = status.exceeds(budget)
assert exceeded is True
assert "Sub-query" in reason
def test_nothing_exceeded(self) -> None:
budget = Budget(
max_tokens=100,
max_cost_usd=1.0,
max_iterations=50,
max_depth=2,
max_wall_time_seconds=300.0,
max_sub_queries=100,
)
status = BudgetStatus(
tokens_used=50,
cost_used=0.5,
iterations_used=10,
depth_current=1,
wall_time_used=60.0,
sub_queries_used=5,
)
exceeded, reason = status.exceeds(budget)
assert exceeded is False
assert reason is None
def test_no_limits_set(self) -> None:
budget = Budget(
max_tokens=None,
max_cost_usd=None,
max_iterations=None,
max_depth=None,
max_wall_time_seconds=None,
max_sub_queries=None,
)
status = BudgetStatus(
tokens_used=999999,
cost_used=999999.0,
iterations_used=999999,
depth_current=999999,
wall_time_used=999999.0,
sub_queries_used=999999,
)
exceeded, reason = status.exceeds(budget)
assert exceeded is False
class TestBudgetDefaults:
"""Tests for Budget default values."""
def test_default_values(self) -> None:
budget = Budget()
assert budget.max_tokens is None
assert budget.max_cost_usd is None
assert budget.max_iterations == 50
assert budget.max_depth == 2
assert budget.max_wall_time_seconds == 300.0
assert budget.max_sub_queries == 100
class TestBudgetStatusDefaults:
"""Tests for BudgetStatus default values."""
def test_default_values(self) -> None:
status = BudgetStatus()
assert status.tokens_used == 0
assert status.cost_used == 0.0
assert status.iterations_used == 0
assert status.depth_current == 0
assert status.wall_time_used == 0.0
assert status.sub_queries_used == 0