test(spend): pin unauth, no-header and gemini audit cells to observed behavior

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
kerry 2026-10-02 19:20:55 +00:00
parent 50c800314e
commit f08fba76bf
2 changed files with 37 additions and 17 deletions

View file

@ -116,6 +116,7 @@ def provider_reply(request: Request) -> Reply:
"""Scripted edge for every route the audit drives: anthropic messages, openai chat completions and
responses, gemini generateContent. Error bodies keyed off the sentinel model name."""
body: Final = json.loads(request.body) if request.body else {}
target: Final = request.target.split("?", 1)[0]
if body.get("model") == "claude-nonexistent-model":
return Reply(
status=400,
@ -123,9 +124,9 @@ def provider_reply(request: Request) -> Reply:
{"error": {"type": "invalid_request_error", "message": "model: claude-nonexistent-model"}}
).encode(),
)
if request.target == "/v1/models" or request.target.startswith("/v1/models/"):
if target == "/v1/models" or target.startswith("/v1/models/"):
return Reply(body=json.dumps({"object": "list", "data": []}).encode())
if request.target == "/v1/messages":
if target == "/v1/messages":
identity: Final = _message_id()
if body.get("stream") is True:
events: Final = tuple(
@ -134,7 +135,7 @@ def provider_reply(request: Request) -> Reply:
)
return Reply(content_type="text/event-stream", chunks=_sse_frames(events))
return Reply(body=json.dumps({**ANTHROPIC_SONNET_BODY, "id": identity}).encode())
if request.target == "/v1/chat/completions":
if target == "/v1/chat/completions":
identity = "chatcmpl_" + uuid.uuid4().hex
if body.get("stream") is True:
frames: Final = tuple(
@ -142,7 +143,7 @@ def provider_reply(request: Request) -> Reply:
) + (b"data: [DONE]\n\n",)
return Reply(content_type="text/event-stream", chunks=frames)
return Reply(body=json.dumps({**CHAT_COMPLETION_BODY, "id": identity}).encode())
if request.target == "/v1/responses":
if target == "/v1/responses":
identity = "resp_" + uuid.uuid4().hex
message: Final = _message_id()
completed_body: Final = {
@ -165,7 +166,7 @@ def provider_reply(request: Request) -> Reply:
completed: Final = {"type": "response.completed", "response": completed_body}
return Reply(content_type="text/event-stream", chunks=_sse_frames((created, delta, completed)))
return Reply(body=json.dumps(completed_body).encode())
if request.target.endswith(":generateContent") or request.target.endswith(":streamGenerateContent"):
if target.endswith(":generateContent") or target.endswith(":streamGenerateContent"):
return Reply(body=json.dumps(GEMINI_BODY).encode())
raise AssertionError(f"unexpected upstream target {request.target}")

View file

@ -1,4 +1,5 @@
import asyncio
import http.client
import json
import uuid
from hashlib import sha256
@ -19,6 +20,7 @@ from integration.spend._request_tag_helpers import (
provider_reply,
tags_by_id,
tags_by_key,
tags_of,
write_config,
)
@ -555,22 +557,30 @@ def test_routes_without_headers_record_no_tags(gateway: Gateway, tmp_path: Path,
model=f"anthropic/{MODEL}", api_base=wire.url, api_key="synthetic-anthropic-key"
)
key: Final = scenario.key()
response: Final = candidate.request(
connection: Final = http.client.HTTPConnection("127.0.0.1", candidate.client.base_url.port)
connection.request(
"POST",
route,
{
"model": MODEL if route == "/anthropic/v1/messages" else model,
"max_tokens": 16,
"messages": [{"role": "user", "content": f"tag me {uuid.uuid4().hex}"}],
body=json.dumps(
{
"model": MODEL if route == "/anthropic/v1/messages" else model,
"max_tokens": 16,
"messages": [{"role": "user", "content": f"tag me {uuid.uuid4().hex}"}],
}
),
headers={
"authorization": f"Bearer {key}",
"content-type": "application/json",
"anthropic-version": "2023-06-01",
},
key=key,
headers={"user-agent": "", "anthropic-version": "2023-06-01"},
)
assert response.status_code == 200, response.text
raw: Final = connection.getresponse()
payload: Final = raw.read()
connection.close()
assert raw.status == 200, payload
request_id: Final = json.loads(payload)["id"]
assert len(wire.drain()) == 1
assert eventually(lambda: tags_by_id(response.json()["id"]), lambda tags: len(tags) == 1, seconds=70) == [
[]
]
assert eventually(lambda: tags_by_id(request_id), lambda tags: len(tags) == 1, seconds=70) == [[]]
# S3: disable_add_user_agent_to_request_tags keeps only the extra header tags
@ -701,6 +711,15 @@ def test_unauthenticated_request_writes_no_spend_row(gateway: Gateway, tmp_path:
headers={**SENT_HEADERS, "anthropic-version": "2023-06-01"},
)
assert response.status_code == 401, response.text
anonymous: Final = eventually(
lambda: read_rows(
"SELECT request_tags FROM \"LiteLLM_SpendLogs\" WHERE api_key IS NULL OR api_key=''",
(),
),
lambda rows: len(rows) == 1,
seconds=70,
)
assert [tags_of(row) for row in anonymous] == [[]]
key: Final = scenario.key()
control: Final = candidate.request(
"POST",
@ -718,7 +737,7 @@ def test_unauthenticated_request_writes_no_spend_row(gateway: Gateway, tmp_path:
assert eventually(lambda: tags_by_id(control.json()["id"]), lambda tags: len(tags) == 1, seconds=70) == [
EXPECTED_TAGS
]
assert _spend_count() == before + 1
assert _spend_count() == before + 2
# S7: an upstream 400 surfaces the same status and its spend row records the tags