Files
hermes-agent/tests/agent/test_credits_tracker.py
2026-06-14 14:30:48 -04:00

910 lines
36 KiB
Python

"""Tests for agent.credits_tracker — CreditsState + parse_credits_headers.
Covers the 9-state matrix plus validation edge cases. All header values
arrive as STRINGS (the producer calls String(...) on every field).
"""
from __future__ import annotations
import logging
import time
from typing import Optional
import pytest
from agent.credits_tracker import CreditsState, parse_credits_headers
# ── Helpers ─────────────────────────────────────────────────────────────────
def micros(dollars: float) -> str:
"""Convert a dollar amount to a micros string for header fixtures."""
return str(round(dollars * 1_000_000))
# ── 9-State matrix fixtures ──────────────────────────────────────────────────
def _base_headers(**overrides) -> dict:
"""Base headers present in every valid response."""
h = {
"x-nous-credits-version": "1",
"x-nous-credits-remaining-micros": micros(0),
"x-nous-credits-remaining-usd": "0.00",
"x-nous-credits-subscription-micros": micros(0),
"x-nous-credits-subscription-usd": "0.00",
"x-nous-credits-rollover-micros": micros(0),
"x-nous-credits-purchased-micros": micros(0),
"x-nous-credits-purchased-usd": "0.00",
"x-nous-tool-pool-micros": micros(0),
"x-nous-tool-pool-gated-off": "false",
"x-nous-credits-denominator-kind": "none",
"x-nous-credits-paid-access": "true",
"x-nous-credits-as-of-ms": "1717000000000",
}
h.update(overrides)
return h
# ── 9 STATES ────────────────────────────────────────────────────────────────
HEALTHY_HEADERS = _base_headers(
**{
"x-nous-credits-remaining-micros": micros(30.34),
"x-nous-credits-remaining-usd": "30.34",
"x-nous-credits-subscription-micros": micros(18.00),
"x-nous-credits-subscription-usd": "18.00",
"x-nous-credits-subscription-limit-micros": micros(20.00),
"x-nous-credits-subscription-limit-usd": "20.00",
"x-nous-credits-rollover-micros": micros(0),
"x-nous-credits-purchased-micros": micros(12.34),
"x-nous-credits-purchased-usd": "12.34",
"x-nous-tool-pool-micros": micros(2.00),
"x-nous-tool-pool-gated-off": "true",
"x-nous-credits-denominator-kind": "subscription_cap",
"x-nous-credits-paid-access": "true",
}
)
SUB_90PCT_HEADERS = _base_headers(
**{
"x-nous-credits-remaining-micros": micros(2.00),
"x-nous-credits-remaining-usd": "2.00",
"x-nous-credits-subscription-micros": micros(2.00),
"x-nous-credits-subscription-usd": "2.00",
"x-nous-credits-subscription-limit-micros": micros(20.00),
"x-nous-credits-subscription-limit-usd": "20.00",
"x-nous-credits-purchased-micros": micros(0),
"x-nous-credits-purchased-usd": "0.00",
"x-nous-credits-denominator-kind": "subscription_cap",
"x-nous-credits-paid-access": "true",
}
)
GRANT_EXHAUSTED_HEADERS = _base_headers(
**{
"x-nous-credits-remaining-micros": micros(12.34),
"x-nous-credits-remaining-usd": "12.34",
"x-nous-credits-subscription-micros": micros(0),
"x-nous-credits-subscription-usd": "0.00",
"x-nous-credits-subscription-limit-micros": micros(20.00),
"x-nous-credits-subscription-limit-usd": "20.00",
"x-nous-credits-purchased-micros": micros(12.34),
"x-nous-credits-purchased-usd": "12.34",
"x-nous-credits-denominator-kind": "subscription_cap",
"x-nous-credits-paid-access": "true",
}
)
PURCHASED_ONLY_HEADERS = _base_headers(
**{
"x-nous-credits-remaining-micros": micros(30.00),
"x-nous-credits-remaining-usd": "30.00",
"x-nous-credits-subscription-micros": micros(0),
"x-nous-credits-subscription-usd": "0.00",
"x-nous-credits-purchased-micros": micros(30.00),
"x-nous-credits-purchased-usd": "30.00",
"x-nous-credits-denominator-kind": "none",
"x-nous-credits-paid-access": "true",
# No limit pair — denominator_kind=none
}
)
TOOL_POOL_FREE_HEADERS = _base_headers(
**{
"x-nous-credits-remaining-micros": micros(0.05),
"x-nous-credits-remaining-usd": "0.05",
"x-nous-tool-pool-micros": micros(0.05),
"x-nous-tool-pool-gated-off": "false",
"x-nous-credits-paid-access": "true",
}
)
DEPLETED_HEADERS = _base_headers(
**{
"x-nous-credits-remaining-micros": micros(0),
"x-nous-credits-remaining-usd": "0.00",
"x-nous-credits-subscription-micros": micros(0),
"x-nous-credits-subscription-usd": "0.00",
"x-nous-credits-purchased-micros": micros(0),
"x-nous-credits-purchased-usd": "0.00",
"x-nous-credits-paid-access": "false",
"x-nous-credits-disabled-reason": "out_of_credits",
}
)
DEBT_HEADERS = _base_headers(
**{
"x-nous-credits-remaining-micros": micros(0),
"x-nous-credits-remaining-usd": "0.00",
"x-nous-credits-subscription-micros": str(-5_000_000),
"x-nous-credits-subscription-usd": "-5.00",
"x-nous-credits-purchased-micros": micros(0),
"x-nous-credits-purchased-usd": "0.00",
"x-nous-credits-paid-access": "false",
}
)
# ── State 1: healthy ─────────────────────────────────────────────────────────
class TestHealthyState:
def test_parses_successfully(self):
state = parse_credits_headers(HEALTHY_HEADERS)
assert state is not None
def test_from_header_set(self):
state = parse_credits_headers(HEALTHY_HEADERS)
assert state.from_header is True
def test_captured_at_set(self):
before = time.time()
state = parse_credits_headers(HEALTHY_HEADERS)
after = time.time()
assert before <= state.captured_at <= after
def test_remaining_fields(self):
state = parse_credits_headers(HEALTHY_HEADERS)
assert state.remaining_micros == round(30.34 * 1_000_000)
assert state.remaining_usd == "30.34"
def test_subscription_fields(self):
state = parse_credits_headers(HEALTHY_HEADERS)
assert state.subscription_micros == round(18.00 * 1_000_000)
assert state.subscription_usd == "18.00"
assert state.subscription_limit_micros == round(20.00 * 1_000_000)
assert state.subscription_limit_usd == "20.00"
def test_rollover_and_purchased(self):
state = parse_credits_headers(HEALTHY_HEADERS)
assert state.rollover_micros == 0
assert state.purchased_micros == round(12.34 * 1_000_000)
assert state.purchased_usd == "12.34"
def test_tool_pool(self):
state = parse_credits_headers(HEALTHY_HEADERS)
assert state.tool_pool_micros == round(2.00 * 1_000_000)
assert state.tool_pool_gated_off is True
def test_denominator_and_access(self):
state = parse_credits_headers(HEALTHY_HEADERS)
assert state.denominator_kind == "subscription_cap"
assert state.paid_access is True
assert state.disabled_reason is None
def test_used_fraction(self):
state = parse_credits_headers(HEALTHY_HEADERS)
# (20.00 - 18.00) / 20.00 = 0.10
assert state.used_fraction == pytest.approx(0.10)
def test_has_data(self):
state = parse_credits_headers(HEALTHY_HEADERS)
assert state.has_data is True
def test_not_depleted(self):
state = parse_credits_headers(HEALTHY_HEADERS)
assert state.depleted is False
def test_age_seconds_reasonable(self):
state = parse_credits_headers(HEALTHY_HEADERS)
# Should be very small — just parsed
assert 0 <= state.age_seconds < 5
# ── State 2: sub_90pct ───────────────────────────────────────────────────────
class TestSub90Pct:
def test_parses_successfully(self):
state = parse_credits_headers(SUB_90PCT_HEADERS)
assert state is not None
def test_used_fraction_90pct(self):
state = parse_credits_headers(SUB_90PCT_HEADERS)
# (20.00 - 2.00) / 20.00 = 0.90
assert state.used_fraction == pytest.approx(0.90)
def test_paid_access(self):
state = parse_credits_headers(SUB_90PCT_HEADERS)
assert state.paid_access is True
assert state.depleted is False
# ── State 3: grant_exhausted ─────────────────────────────────────────────────
class TestGrantExhausted:
def test_used_fraction_100pct(self):
state = parse_credits_headers(GRANT_EXHAUSTED_HEADERS)
assert state is not None
# subscription_micros=0, limit=20.00 → (20-0)/20 = 1.0
assert state.used_fraction == pytest.approx(1.0)
def test_paid_access_still_true(self):
state = parse_credits_headers(GRANT_EXHAUSTED_HEADERS)
assert state.paid_access is True
assert state.depleted is False
# ── State 4: purchased_only ──────────────────────────────────────────────────
class TestPurchasedOnly:
def test_parses_successfully(self):
state = parse_credits_headers(PURCHASED_ONLY_HEADERS)
assert state is not None
def test_denominator_kind_none(self):
state = parse_credits_headers(PURCHASED_ONLY_HEADERS)
assert state.denominator_kind == "none"
def test_used_fraction_is_none_no_limit(self):
state = parse_credits_headers(PURCHASED_ONLY_HEADERS)
# No subscription_limit_micros → used_fraction is None
assert state.used_fraction is None
def test_no_limit_pair(self):
state = parse_credits_headers(PURCHASED_ONLY_HEADERS)
assert state.subscription_limit_micros is None
assert state.subscription_limit_usd is None
# ── State 5: tool_pool_free ──────────────────────────────────────────────────
class TestToolPoolFree:
def test_parses_successfully(self):
state = parse_credits_headers(TOOL_POOL_FREE_HEADERS)
assert state is not None
def test_tool_pool_gated_off_false(self):
state = parse_credits_headers(TOOL_POOL_FREE_HEADERS)
assert state.tool_pool_gated_off is False
def test_tool_pool_micros(self):
state = parse_credits_headers(TOOL_POOL_FREE_HEADERS)
assert state.tool_pool_micros == round(0.05 * 1_000_000)
def test_paid_access(self):
state = parse_credits_headers(TOOL_POOL_FREE_HEADERS)
assert state.paid_access is True
# ── State 6: depleted ────────────────────────────────────────────────────────
class TestDepleted:
def test_parses_successfully(self):
state = parse_credits_headers(DEPLETED_HEADERS)
assert state is not None
def test_paid_access_false(self):
state = parse_credits_headers(DEPLETED_HEADERS)
assert state.paid_access is False
def test_depleted_true(self):
state = parse_credits_headers(DEPLETED_HEADERS)
assert state.depleted is True
def test_disabled_reason(self):
state = parse_credits_headers(DEPLETED_HEADERS)
assert state.disabled_reason == "out_of_credits"
def test_remaining_zero(self):
state = parse_credits_headers(DEPLETED_HEADERS)
assert state.remaining_micros == 0
# ── State 7: debt ────────────────────────────────────────────────────────────
class TestDebt:
def test_parses_successfully(self):
# Negative subscription_micros should NOT cause the parse to fail
state = parse_credits_headers(DEBT_HEADERS)
assert state is not None
def test_negative_subscription_accepted(self):
state = parse_credits_headers(DEBT_HEADERS)
assert state.subscription_micros == -5_000_000
def test_negative_subscription_usd_accepted(self):
state = parse_credits_headers(DEBT_HEADERS)
assert state.subscription_usd == "-5.00"
def test_paid_access_false(self):
state = parse_credits_headers(DEBT_HEADERS)
assert state.paid_access is False
assert state.depleted is True
# ── State 8: missing ─────────────────────────────────────────────────────────
class TestMissing:
def test_no_credits_headers_returns_none(self):
state = parse_credits_headers({})
assert state is None
def test_completely_empty_dict(self):
assert parse_credits_headers({}) is None
# ── State 9: no_org ──────────────────────────────────────────────────────────
class TestNoOrg:
def test_irrelevant_headers_return_none(self):
headers = {
"content-type": "application/json",
"x-request-id": "abc123",
"server": "nginx",
}
state = parse_credits_headers(headers)
assert state is None
def test_api_key_path_no_org_returns_none(self):
# Headers that might appear on an api-key path with no org
headers = {
"content-type": "application/json",
"authorization": "Bearer sk-test",
}
assert parse_credits_headers(headers) is None
# ── Version validation ───────────────────────────────────────────────────────
class TestVersionValidation:
def test_version_string_1_parses(self):
headers = _base_headers(**{"x-nous-credits-version": "1"})
state = parse_credits_headers(headers)
assert state is not None
assert state.version == 1
def test_version_2_returns_none(self):
headers = _base_headers(**{"x-nous-credits-version": "2"})
state = parse_credits_headers(headers)
assert state is None
def test_version_absent_returns_none(self):
headers = {k: v for k, v in _base_headers().items() if k != "x-nous-credits-version"}
state = parse_credits_headers(headers)
assert state is None
def test_version_greater_than_1_warns_once(self, caplog):
"""Version > 1 must log a warning, and ONLY ONCE across multiple calls."""
import agent.credits_tracker as ct
original = ct._version_warning_emitted
try:
# Reset the warn-once latch so this test starts clean regardless of order
ct._version_warning_emitted = False
headers = _base_headers(**{"x-nous-credits-version": "3"})
with caplog.at_level(logging.WARNING, logger="agent.credits_tracker"):
parse_credits_headers(headers)
parse_credits_headers(headers)
parse_credits_headers(headers)
warning_records = [r for r in caplog.records if "unsupported" in r.message.lower() or "version" in r.message.lower()]
assert len(warning_records) == 1, (
f"Expected exactly 1 version warning, got {len(warning_records)}: {[r.message for r in warning_records]}"
)
finally:
ct._version_warning_emitted = original
def test_version_0_returns_none(self):
headers = _base_headers(**{"x-nous-credits-version": "0"})
assert parse_credits_headers(headers) is None
def test_version_non_int_returns_none(self):
headers = _base_headers(**{"x-nous-credits-version": "abc"})
assert parse_credits_headers(headers) is None
# ── Bool-string trap ─────────────────────────────────────────────────────────
class TestBoolStringTrap:
"""Explicit tests for the bool("false") == True trap."""
def test_paid_access_string_false_means_depleted(self):
"""paid_access='false' must yield paid_access=False — NOT True."""
headers = _base_headers(**{"x-nous-credits-paid-access": "false"})
state = parse_credits_headers(headers)
assert state is not None
assert state.paid_access is False
assert state.depleted is True
def test_paid_access_string_true_means_not_depleted(self):
headers = _base_headers(**{"x-nous-credits-paid-access": "true"})
state = parse_credits_headers(headers)
assert state is not None
assert state.paid_access is True
assert state.depleted is False
def test_paid_access_case_insensitive_FALSE(self):
headers = _base_headers(**{"x-nous-credits-paid-access": "FALSE"})
state = parse_credits_headers(headers)
assert state is not None
assert state.paid_access is False
def test_paid_access_case_insensitive_True(self):
headers = _base_headers(**{"x-nous-credits-paid-access": "True"})
state = parse_credits_headers(headers)
assert state is not None
assert state.paid_access is True
def test_tool_pool_gated_off_false(self):
headers = _base_headers(**{"x-nous-tool-pool-gated-off": "false"})
state = parse_credits_headers(headers)
assert state is not None
assert state.tool_pool_gated_off is False
def test_tool_pool_gated_off_true(self):
headers = _base_headers(**{"x-nous-tool-pool-gated-off": "true"})
state = parse_credits_headers(headers)
assert state is not None
assert state.tool_pool_gated_off is True
# ── Tool-pool optional headers ────────────────────────────────────────────────
class TestToolPoolOptional:
"""x-nous-tool-pool-* headers are optional; absent → defaults; present-but-malformed → miss."""
def _no_tool_pool_headers(self) -> dict:
"""Base headers with BOTH tool-pool headers removed."""
h = _base_headers()
h.pop("x-nous-tool-pool-micros", None)
h.pop("x-nous-tool-pool-gated-off", None)
return h
def test_absent_tool_pool_headers_parse_succeeds(self):
"""Valid credits headers with no x-nous-tool-pool-* → parse succeeds."""
state = parse_credits_headers(self._no_tool_pool_headers())
assert state is not None
def test_absent_tool_pool_micros_defaults_to_zero(self):
state = parse_credits_headers(self._no_tool_pool_headers())
assert state.tool_pool_micros == 0
def test_absent_tool_pool_gated_off_defaults_to_false(self):
state = parse_credits_headers(self._no_tool_pool_headers())
assert state.tool_pool_gated_off is False
def test_present_malformed_tool_pool_micros_returns_none(self):
"""x-nous-tool-pool-micros present but non-int → parse miss (returns None)."""
headers = _base_headers(**{"x-nous-tool-pool-micros": "not-a-number"})
assert parse_credits_headers(headers) is None
def test_present_negative_tool_pool_micros_returns_none(self):
"""x-nous-tool-pool-micros present but negative → parse miss (returns None)."""
headers = _base_headers(**{"x-nous-tool-pool-micros": "-1000"})
assert parse_credits_headers(headers) is None
def test_only_tool_pool_micros_absent_still_succeeds(self):
"""Only micros absent (gated-off still present) → tool_pool_micros = 0, parse succeeds."""
h = _base_headers()
h.pop("x-nous-tool-pool-micros", None)
state = parse_credits_headers(h)
assert state is not None
assert state.tool_pool_micros == 0
# ── Half-pair subscription limit ─────────────────────────────────────────────
class TestHalfPairLimit:
def test_only_limit_micros_present_both_absent(self):
"""Only -micros present → both None, parse SUCCEEDS."""
headers = _base_headers(
**{
"x-nous-credits-subscription-limit-micros": micros(20.00),
"x-nous-credits-denominator-kind": "subscription_cap",
}
)
state = parse_credits_headers(headers)
assert state is not None
assert state.subscription_limit_micros is None
assert state.subscription_limit_usd is None
def test_only_limit_usd_present_both_absent(self):
"""Only -usd present → both None, parse SUCCEEDS."""
headers = _base_headers(
**{
"x-nous-credits-subscription-limit-usd": "20.00",
"x-nous-credits-denominator-kind": "subscription_cap",
}
)
state = parse_credits_headers(headers)
assert state is not None
assert state.subscription_limit_micros is None
assert state.subscription_limit_usd is None
def test_half_pair_used_fraction_is_none(self):
"""With no limit pair, used_fraction is None regardless of denominator_kind."""
headers = _base_headers(
**{
"x-nous-credits-subscription-limit-micros": micros(20.00),
"x-nous-credits-denominator-kind": "subscription_cap",
}
)
state = parse_credits_headers(headers)
assert state is not None
assert state.used_fraction is None
def test_full_pair_present_parsed_correctly(self):
"""Both present → both populated, used_fraction computable."""
headers = _base_headers(
**{
"x-nous-credits-subscription-micros": micros(10.00),
"x-nous-credits-subscription-usd": "10.00",
"x-nous-credits-subscription-limit-micros": micros(20.00),
"x-nous-credits-subscription-limit-usd": "20.00",
"x-nous-credits-denominator-kind": "subscription_cap",
}
)
state = parse_credits_headers(headers)
assert state is not None
assert state.subscription_limit_micros == round(20.00 * 1_000_000)
assert state.subscription_limit_usd == "20.00"
assert state.used_fraction == pytest.approx(0.50)
# ── Negative value validation ─────────────────────────────────────────────────
class TestNegativeValues:
def test_negative_remaining_micros_returns_none(self):
headers = _base_headers(**{"x-nous-credits-remaining-micros": "-1000"})
assert parse_credits_headers(headers) is None
def test_negative_purchased_micros_returns_none(self):
headers = _base_headers(**{"x-nous-credits-purchased-micros": "-500"})
assert parse_credits_headers(headers) is None
def test_negative_rollover_micros_returns_none(self):
headers = _base_headers(**{"x-nous-credits-rollover-micros": "-100"})
assert parse_credits_headers(headers) is None
def test_negative_limit_micros_returns_none(self):
headers = _base_headers(
**{
"x-nous-credits-subscription-limit-micros": "-1000",
"x-nous-credits-subscription-limit-usd": "-0.00",
"x-nous-credits-denominator-kind": "subscription_cap",
}
)
assert parse_credits_headers(headers) is None
def test_negative_subscription_accepted(self):
"""subscription_micros is the ONLY field allowed to be negative."""
headers = _base_headers(**{"x-nous-credits-subscription-micros": "-5000000",
"x-nous-credits-subscription-usd": "-5.00"})
state = parse_credits_headers(headers)
assert state is not None
assert state.subscription_micros == -5_000_000
# ── USD format validation ─────────────────────────────────────────────────────
class TestUsdValidation:
def test_valid_usd_format(self):
headers = _base_headers(**{"x-nous-credits-remaining-usd": "18.00"})
state = parse_credits_headers(headers)
assert state is not None
assert state.remaining_usd == "18.00"
def test_usd_one_decimal_returns_none(self):
"""'18.0' does not match ^-?\d+\.\d{2}$"""
headers = _base_headers(**{"x-nous-credits-remaining-usd": "18.0"})
assert parse_credits_headers(headers) is None
def test_usd_no_decimal_returns_none(self):
headers = _base_headers(**{"x-nous-credits-remaining-usd": "18"})
assert parse_credits_headers(headers) is None
def test_usd_with_dollar_sign_returns_none(self):
headers = _base_headers(**{"x-nous-credits-remaining-usd": "$18.00"})
assert parse_credits_headers(headers) is None
def test_usd_with_comma_returns_none(self):
headers = _base_headers(**{"x-nous-credits-remaining-usd": "1,800.00"})
assert parse_credits_headers(headers) is None
def test_usd_negative_valid(self):
"""Negative USD string should parse (e.g. subscription debt)."""
headers = _base_headers(
**{
"x-nous-credits-subscription-micros": "-5000000",
"x-nous-credits-subscription-usd": "-5.00",
}
)
state = parse_credits_headers(headers)
assert state is not None
assert state.subscription_usd == "-5.00"
# ── Non-int micros validation ─────────────────────────────────────────────────
class TestMicrosValidation:
def test_non_int_micros_string_returns_none(self):
headers = _base_headers(**{"x-nous-credits-remaining-micros": "abc"})
assert parse_credits_headers(headers) is None
def test_float_string_micros_returns_none(self):
"""'1.5' is not an integer string — should fail validation."""
headers = _base_headers(**{"x-nous-credits-remaining-micros": "1.5"})
assert parse_credits_headers(headers) is None
def test_non_int_purchased_returns_none(self):
headers = _base_headers(**{"x-nous-credits-purchased-micros": "abc"})
assert parse_credits_headers(headers) is None
# ── as_of_ms validation ───────────────────────────────────────────────────────
class TestAsOfMs:
def test_junk_as_of_ms_returns_none(self):
headers = _base_headers(**{"x-nous-credits-as-of-ms": "not-a-timestamp"})
assert parse_credits_headers(headers) is None
def test_valid_as_of_ms(self):
headers = _base_headers(**{"x-nous-credits-as-of-ms": "1717000000000"})
state = parse_credits_headers(headers)
assert state is not None
assert state.as_of_ms == 1717000000000
# ── denominator_kind validation ────────────────────────────────────────────────
class TestDenominatorKind:
def test_subscription_cap_valid(self):
headers = _base_headers(
**{
"x-nous-credits-denominator-kind": "subscription_cap",
"x-nous-credits-subscription-limit-micros": micros(20.00),
"x-nous-credits-subscription-limit-usd": "20.00",
}
)
state = parse_credits_headers(headers)
assert state is not None
assert state.denominator_kind == "subscription_cap"
def test_none_valid(self):
headers = _base_headers(**{"x-nous-credits-denominator-kind": "none"})
state = parse_credits_headers(headers)
assert state is not None
assert state.denominator_kind == "none"
def test_invalid_denominator_kind_returns_none(self):
headers = _base_headers(**{"x-nous-credits-denominator-kind": "invalid_kind"})
assert parse_credits_headers(headers) is None
# ── Zero-division guard ────────────────────────────────────────────────────────
class TestZeroDivisionGuard:
def test_subscription_limit_zero_used_fraction_is_none(self):
"""subscription_limit_micros='0' + subscription_cap → used_fraction is None (no ZeroDivisionError)."""
headers = _base_headers(
**{
"x-nous-credits-subscription-limit-micros": "0",
"x-nous-credits-subscription-limit-usd": "0.00",
"x-nous-credits-denominator-kind": "subscription_cap",
}
)
state = parse_credits_headers(headers)
assert state is not None
# limit == 0, so used_fraction must be None (guard prevents division)
assert state.used_fraction is None
# ── Unknown headers ignored ────────────────────────────────────────────────────
class TestUnknownHeaders:
def test_unknown_extra_header_ignored(self):
headers = {
**_base_headers(),
"x-nous-credits-future-field": "some-value",
"x-request-id": "abc123",
}
state = parse_credits_headers(headers)
assert state is not None
def test_mixed_with_other_providers_headers(self):
headers = {
**_base_headers(),
"x-ratelimit-limit-requests": "800",
"content-type": "application/json",
}
state = parse_credits_headers(headers)
assert state is not None
# ── Header normalization ──────────────────────────────────────────────────────
class TestHeaderNormalization:
def test_uppercase_headers_parsed(self):
headers = {k.upper(): v for k, v in _base_headers().items()}
state = parse_credits_headers(headers)
assert state is not None
def test_mixed_case_headers_parsed(self):
headers = {
"X-Nous-Credits-Version": "1",
"X-Nous-Credits-Remaining-Micros": micros(5.00),
"X-Nous-Credits-Remaining-Usd": "5.00",
"X-Nous-Credits-Subscription-Micros": micros(5.00),
"X-Nous-Credits-Subscription-Usd": "5.00",
"X-Nous-Credits-Rollover-Micros": "0",
"X-Nous-Credits-Purchased-Micros": "0",
"X-Nous-Credits-Purchased-Usd": "0.00",
"X-Nous-Tool-Pool-Micros": "0",
"X-Nous-Tool-Pool-Gated-Off": "false",
"X-Nous-Credits-Denominator-Kind": "none",
"X-Nous-Credits-Paid-Access": "true",
"X-Nous-Credits-As-Of-Ms": "1717000000000",
}
state = parse_credits_headers(headers)
assert state is not None
assert state.remaining_micros == round(5.00 * 1_000_000)
# ── CreditsState dataclass defaults ──────────────────────────────────────────
class TestCreditsStateDefaults:
def test_default_state(self):
state = CreditsState()
assert state.version == 0
assert state.remaining_micros == 0
assert state.remaining_usd == ""
assert state.subscription_micros == 0
assert state.subscription_usd == ""
assert state.subscription_limit_micros is None
assert state.subscription_limit_usd is None
assert state.rollover_micros == 0
assert state.purchased_micros == 0
assert state.purchased_usd == ""
assert state.tool_pool_micros == 0
assert state.tool_pool_gated_off is False
assert state.denominator_kind == "none"
assert state.paid_access is True
assert state.disabled_reason is None
assert state.as_of_ms == 0
assert state.captured_at == 0.0
assert state.from_header is False
def test_has_data_false_when_no_captured_at(self):
state = CreditsState()
assert state.has_data is False
def test_age_seconds_inf_when_no_data(self):
state = CreditsState()
assert state.age_seconds == float("inf")
def test_depleted_false_by_default(self):
state = CreditsState()
assert state.depleted is False
def test_used_fraction_none_by_default(self):
state = CreditsState()
assert state.used_fraction is None
# ── depleted property ─────────────────────────────────────────────────────────
class TestDepletedProperty:
def test_depleted_equals_not_paid_access(self):
"""depleted must be exactly `not paid_access`, never `remaining==0`."""
state = CreditsState(paid_access=False, remaining_micros=0, captured_at=time.time())
assert state.depleted is True
def test_not_depleted_when_paid_access_true(self):
state = CreditsState(paid_access=True, remaining_micros=0, captured_at=time.time())
# remaining==0 but paid_access is True → NOT depleted
assert state.depleted is False
def test_depleted_independent_of_remaining(self):
"""Even with remaining > 0, if paid_access is False, depleted is True."""
state = CreditsState(paid_access=False, remaining_micros=1_000_000, captured_at=time.time())
assert state.depleted is True
# ── used_fraction edge cases ──────────────────────────────────────────────────
class TestUsedFraction:
def test_none_without_limit(self):
state = CreditsState(
denominator_kind="subscription_cap",
subscription_limit_micros=None,
captured_at=time.time(),
)
assert state.used_fraction is None
def test_none_when_limit_zero(self):
state = CreditsState(
denominator_kind="subscription_cap",
subscription_limit_micros=0,
subscription_micros=0,
captured_at=time.time(),
)
assert state.used_fraction is None
def test_clamped_at_zero(self):
"""If subscription_micros > limit (over-credited), fraction clamps to 0."""
state = CreditsState(
denominator_kind="subscription_cap",
subscription_limit_micros=10_000_000,
subscription_micros=15_000_000, # more than limit
captured_at=time.time(),
)
assert state.used_fraction == pytest.approx(0.0)
def test_clamped_at_one(self):
"""If subscription_micros is very negative (debt), fraction clamps to 1.0."""
state = CreditsState(
denominator_kind="subscription_cap",
subscription_limit_micros=10_000_000,
subscription_micros=-5_000_000, # deep debt
captured_at=time.time(),
)
assert state.used_fraction == pytest.approx(1.0)
def test_guarded_by_limit_field_not_denominator(self):
"""used_fraction depends on subscription_limit_micros being truthy, not denominator_kind."""
# limit present but denominator_kind="none" — spec says guard on LIMIT FIELD
state = CreditsState(
denominator_kind="none",
subscription_limit_micros=20_000_000,
subscription_micros=10_000_000,
captured_at=time.time(),
)
# With limit_micros set, fraction should be computable regardless of denominator_kind
assert state.used_fraction == pytest.approx(0.50)
def test_none_when_denominator_cap_but_no_limit(self):
"""denominator_kind=subscription_cap but no limit pair → None."""
state = CreditsState(
denominator_kind="subscription_cap",
subscription_limit_micros=None,
subscription_micros=5_000_000,
captured_at=time.time(),
)
assert state.used_fraction is None