Files
routstr-core/tests/unit
9qeklajc a7d4e2832d fix: gate upstream-reported cost behind a per-provider trust policy
A positive cost reported by an upstream pre-empted token pricing with no
check on who reported it. Because the bearer overrun path settles
min(chargeable, total) against the key's balance minus sibling
reservations, any configured or chained provider that controls an
accepted cost field could bill far beyond the reservation it was
authorized against and drain the key. The mirror case bled the operator:
an under-reporting provider with omitted token usage settled at its own
low number.

Reported cost is now honoured only for provider types that opt in via
BaseUpstreamProvider.trusts_reported_cost, which defaults to off. A new
provider therefore prices from tokens until someone deliberately approves
it. PPQ.AI (BYOK — only PPQ knows the user's upstream bill) and
OpenRouter (per-request sub-provider routing) are approved; chained
Routstr peers and generic/custom rows are not. This is a policy gate, not
a clamp: PPQ BYOK legitimately settles above the reservation and still
does.

The flag is threaded from the serving provider instance through
adjust_payment_for_tokens to calculate_cost alongside provider_fee, at
every streaming and non-streaming settlement site in the upstream base
provider, so the two paths agree.

Two supporting changes:

- _coerce_usd rejects non-finite input. Infinity previously survived the
  clamp and reached math.ceil, where the OverflowError was swallowed by
  the USD path's broad handler — correct by accident. NaN was already
  folded to zero by max() comparison semantics; it is now explicit.
  Nothing about int/float msats arithmetic changed, so billing amounts
  are unaffected.

- A trusted provider's cost is compared against what its own reported
  tokens would have been priced at, and against the reservation. Ratios
  outside the bounds are logged in both directions. They are not
  clamped: the legitimate BYOK spread is wide enough that clamping would
  mis-bill real traffic, so the goal is that a mis-report is visible
  rather than silent.

Existing USD-path tests now declare their provider as cost-reporting;
no assertion was changed.
2026-08-25 00:38:12 +02:00
..
2025-08-03 20:35:59 -03:00
2025-08-09 14:55:26 -03:00
2026-08-23 23:25:03 +02:00
2026-08-03 23:32:06 +02:00
2026-06-13 23:40:39 +02:00
2026-08-16 14:59:38 +02:00
2026-08-03 23:32:06 +02:00
2026-08-06 22:58:44 +02:00
2026-08-04 00:06:53 +02:00
2026-08-03 00:05:36 +02:00
2026-08-03 23:32:06 +02:00
2026-08-02 23:16:01 +02:00
2026-08-23 13:30:57 +02:00
2026-07-01 17:08:28 +02:00
2026-07-01 16:53:52 +02:00
2026-05-14 15:40:49 +02:00
2026-07-29 22:50:33 +02:00
2026-08-14 21:48:29 +02:00
2026-07-22 23:10:27 +02:00
2026-07-22 23:10:27 +02:00
2026-08-15 15:09:00 +02:00

FastAPI Async Unit Tests

This directory contains async unit tests for the Routstr proxy FastAPI application.

Installation

First, ensure you have the development dependencies installed:

uv pip install -e ".[dev]"

Running Tests

To run all tests:

pytest

To run tests with coverage:

pytest --cov=routstr --cov-report=html

To run specific test files:

pytest tests/test_main.py
pytest tests/test_models.py
pytest tests/test_proxy.py

To run only async tests:

pytest -m asyncio

Test Structure

  • conftest.py - Pytest fixtures and configuration
  • test_main.py - Tests for main app endpoints
  • test_account.py - Tests for wallet/account management endpoints
  • test_proxy.py - Tests for the proxy functionality with mocked upstream
  • test_models.py - Tests for model pricing and data structures

Key Fixtures

  • async_client - Async HTTP client for testing FastAPI endpoints
  • test_session - In-memory SQLite database session for tests
  • test_api_key - Pre-configured API key with balance
  • api_key_with_balance - API key with sufficient balance for proxy tests

Environment Variables

The tests automatically set up required environment variables in conftest.py. No manual configuration needed.

Writing New Tests

  1. Use @pytest.mark.asyncio for async tests
  2. Use the provided fixtures for database and client access
  3. Mock external dependencies (like upstream API calls)
  4. Test both success and error cases
  5. Verify database state changes when applicable