mirror of
https://github.com/BerriAI/litellm.git
synced 2026-11-08 08:08:37 +00:00
* feat(rust-bridge): scope catalog rules with a contextvar Co-Authored-By: Yujong Lee <yujong@berri.ai> * test(rust-bridge): select native integration routes with scoped rules Co-Authored-By: Yujong Lee <yujong@berri.ai> * test(rust-bridge): run the Rust extension suite without LITELLM_RUST Co-Authored-By: Yujong Lee <yujong@berri.ai> * test(rust-bridge): use scoped catalog rules in dispatch tests Co-Authored-By: Yujong Lee <yujong@berri.ai> * refactor(rust-bridge): keep catalog rules a static global and override them once per test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
27 lines
3 KiB
Markdown
27 lines
3 KiB
Markdown
# Invariants
|
|
|
|
- This directory tests the Rust path and nothing else. Treat the Python implementation of every route as already removed. Never call it on purpose, never run one request through both engines, and never compare Python and Rust outputs, headers, cache keys or logs
|
|
- A test that would still pass with Python serving the call does not belong here. Every test asserts the call was served natively with `support.routing.assert_served_natively`
|
|
- Select the Rust path with `support.routing.native_route(...)`, which prepends `RUST_REQUIRED` rules to `catalog.RULES` and restores them on exit. Each route folder's `conftest.py` applies it to every test through an autouse fixture. A test outside a route folder wraps its whole body in one `native_route(...)` block, and a child interpreter script assigns `catalog.RULES` once at its top. Never select a backend by reading or setting `LITELLM_RUST`, calling `litellm.rust(...)` or rebinding `catalog.RULES` any other way. The rollout in `litellm/rust_bridge/catalog.py` is a product decision, and a test here must pass no matter what it says, including for a route marked `PYTHON_ONLY`
|
|
- `catalog.RULES` is static at runtime and `native_route(...)` swaps a module global, so open it once per test and never per call. Two overlapping blocks, such as one per task inside an `asyncio.gather`, restore out of order and leave the wrong rules behind for later tests
|
|
- A test whose subject is the rollout switch itself (env, `litellm.rust(...)`, catalog rules) is a unit test of `litellm/rust_bridge/configuration.py` or `catalog.py` and lives in `tests/unit/rust_bridge/`
|
|
- A test lives here only when it cannot be written in Rust. That means it needs the Python public API, Python-owned state such as `litellm.cache` and callbacks, or the process boundary (fork, threads, event loops). Anything checkable from the Rust side goes in the crate's own tests
|
|
- The wire is the local recording server. No test here reaches a real provider
|
|
- Never parametrize one test across routes. Each route folder owns its tests, its `server` fixture, its request data and its `call`
|
|
- Call `_native` directly only for a case the public API cannot reach
|
|
|
|
# Layout
|
|
|
|
Each route folder (`ocr/`, `messages/`, `responses/`, `chat_completions/`) uses the same file names, one concern per file
|
|
|
|
- `test_dispatch.py` the call reaches the native route
|
|
- `test_requests.py` Python inputs that reach the wire
|
|
- `test_failures.py` errors raised to the caller and rejection before provider IO
|
|
- `test_settings.py` globals, env, named credentials and their precedence
|
|
- `test_streaming.py` stream relay, early close and stream-time logging
|
|
- `test_callbacks.py` the logger hook contract
|
|
- `test_body_hooks.py` handler body hooks such as interceptors and agentic loops
|
|
- `test_lifecycle.py` cancellation, concurrency, context and nested calls
|
|
- `test_cache.py` the configured cache seen from this route
|
|
|
|
Route data and the route's `call` live in `<route>/data.py`, and `<route>/conftest.py` owns the `server` fixture and the autouse `native` fixture. `support/` holds only route-neutral helpers
|