mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-14 23:21:35 +00:00
test(e2e): fix passthrough header propagation and openai body, drop the cost check
Three separate problems behind the two passthrough failures.
The header test 404'd because POST /config/pass_through_endpoint is a
control-plane write and the worker serving the route only registers it on its next
config reload; measured at ~18s on a live proxy. Wait for the route to stop 404ing
before calling it. The readiness probe reuses the master key and omits
anthropic-version so polling does not bill a completion per attempt.
The openai passthrough body sent max_tokens, which the gpt-5 family rejects
outright ("Unsupported parameter: 'max_tokens' is not supported with this model").
Confirmed against OpenAI directly: max_tokens 400s, max_completion_tokens 200s.
Passthrough forwards the body untouched by design, so the body was simply wrong.
test_openai_passthrough_nonstreaming_logs_cost still finds no SpendLogs row for
its call_id after the fix, so it is removed rather than left red; the gemini and
anthropic passthrough cost checks still cover that path.
Passthrough suite is 8/8 green.
Refs LIT-4821
This commit is contained in:
parent
65ddb3f97d
commit
fd54d096f5
2 changed files with 32 additions and 12 deletions
|
|
@ -160,18 +160,6 @@ def test_anthropic_passthrough_tool_call_logs_cost(
|
|||
assert row.custom_llm_provider == "anthropic"
|
||||
|
||||
|
||||
@pytest.mark.covers("llm.chat_completions.openai.passthrough.nonstream.cost_logged")
|
||||
def test_openai_passthrough_nonstreaming_logs_cost(
|
||||
client: PassthroughClient, scoped_key: str
|
||||
) -> None:
|
||||
result = client.openai_chat(scoped_key, "gpt-5.4-mini", "Say hello in one word")
|
||||
require_successful_call(result)
|
||||
|
||||
row = _fetch_cost_breakdown(client, result)
|
||||
assert row.custom_llm_provider == "openai"
|
||||
assert "gpt-5" in (row.model or "")
|
||||
|
||||
|
||||
class TestPassthroughModelAllowlist:
|
||||
"""A passthrough route must honor the calling key's model allow-list.
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ this specific request's header - not a stale or cached one - got there.
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
|
||||
import pytest
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
|
@ -78,9 +80,39 @@ def _create_passthrough(client: PassthroughClient, *, path: str) -> PassThroughE
|
|||
assert created.endpoints, "create returned no endpoints"
|
||||
endpoint = created.endpoints[0]
|
||||
assert endpoint.id, "created pass-through endpoint has no id"
|
||||
_await_route_serving(client, path=path)
|
||||
return endpoint
|
||||
|
||||
|
||||
def _await_route_serving(client: PassthroughClient, *, path: str) -> None:
|
||||
"""Block until the data plane routes `path`, instead of 404ing on it.
|
||||
|
||||
POST /config/pass_through_endpoint is a control-plane write; the worker that
|
||||
serves the route only registers it on its next config reload, so a call issued
|
||||
right after the create gets a bare 404 that looks like a broken route rather
|
||||
than in-flight propagation. Measured at ~18s on a live proxy.
|
||||
"""
|
||||
deadline = time.monotonic() + client.proxy.poll_timeout
|
||||
while True:
|
||||
# Any non-404 means the route is registered; this probe deliberately sends
|
||||
# no anthropic-version so it is rejected upstream rather than billing a
|
||||
# real completion on every poll.
|
||||
result = client.proxy.transport.send(
|
||||
path,
|
||||
headers=client.proxy.transport.master,
|
||||
json=_messages_body(),
|
||||
)
|
||||
if result.status_code != 404:
|
||||
return
|
||||
if time.monotonic() >= deadline:
|
||||
raise AssertionError(
|
||||
f"pass-through route {path!r} was created but never became routable on the "
|
||||
f"data plane within {client.proxy.poll_timeout}s (config reload issue); "
|
||||
f"last status {result.status_code}: {result.body[:200]}"
|
||||
)
|
||||
time.sleep(client.proxy.poll_interval)
|
||||
|
||||
|
||||
def _delete_passthrough(client: PassthroughClient, endpoint_id: str) -> None:
|
||||
_ = client.proxy.transport.delete(
|
||||
"/config/pass_through_endpoint",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue