litellm/tests/integration/spend/test_container_spend.py
devin-ai-integration[bot] 90a503d98c
test(integration): cover videos_containers endpoint contracts (#44691)
* test(integration): cover videos_containers endpoint contracts

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(integration): end the first container page on an ownerless id

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(integration): assert container upload parts, SDK video extend, bare video ids, cost from map

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(integration): catch a stale container list cache, cover video edit JSON, bracketed video refs and object input_reference

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(integration): pin container optional fields, video client extras and the /videos alias on the wire

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* test(integration): pin multipart character id decoding on video create as a BUG skip

Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

---------

Co-authored-by: mateo <mateo@berri.ai>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
2026-10-14 03:49:01 +00:00

76 lines
3.4 KiB
Python

import json
import uuid
from hashlib import sha256
from pathlib import Path
from typing import Final
import litellm
import pytest
from integration._support.client import Gateway, eventually
from integration._support.database import read_rows
from integration._support.wire import Reply, Request, wire_server
from openai import OpenAI
from openai.types import ContainerCreateResponse
# run.py sets LITELLM_LOCAL_MODEL_COST_MAP=True and reads model_prices_and_context_window_backup.json
CODE_INTERPRETER_SESSION_COST: Final = float(
json.loads((Path(litellm.__file__).parent / "model_prices_and_context_window_backup.json").read_text())[
"openai/container"
]["code_interpreter_cost_per_session"]
)
PROVIDER_KEY: Final = "synthetic-container-key"
def test_container_create_charges_one_code_interpreter_session(gateway: Gateway) -> None:
assert CODE_INTERPRETER_SESSION_COST > 0
container_id: Final = f"cntr_spend_{uuid.uuid4().hex}"
scripted: Final = {"id": container_id, "object": "container", "created_at": 1, "status": "running", "name": "c"}
def respond(request: Request) -> Reply:
return Reply(body=json.dumps(scripted).encode())
with wire_server(respond) as wire, gateway.scenario() as scenario:
model: Final = scenario.model(model="openai/gpt-4o-mini", api_base=f"{wire.url}/v1", api_key=PROVIDER_KEY)
key: Final = scenario.key()
digest: Final = sha256(key.encode()).hexdigest()
client: Final = OpenAI(base_url=str(gateway.client.base_url.join("/v1")), api_key=key, max_retries=0)
eventually(lambda: tuple(entry.id for entry in client.models.list()), lambda ids: model in ids)
raw: Final = client.containers.with_raw_response.create(
name="c",
expires_after={"anchor": "last_active_at", "minutes": 5},
file_ids=["file-spend"],
extra_body={"model": model},
)
assert raw.http_response.status_code == 200, raw.http_response.text
created: Final = raw.parse()
assert created.model_copy(update={"id": container_id}) == ContainerCreateResponse.model_validate(scripted), (
raw.http_response.text
)
assert float(raw.headers["x-litellm-response-cost"]) == pytest.approx(CODE_INTERPRETER_SESSION_COST), dict(
raw.headers
)
requests: Final = wire.drain()
assert [(request.method, request.target, request.headers["authorization"]) for request in requests] == [
("POST", "/v1/containers", f"Bearer {PROVIDER_KEY}")
]
assert json.loads(requests[0].body) == {
"name": "c",
"expires_after": {"anchor": "last_active_at", "minutes": 5},
"file_ids": ["file-spend"],
}, requests[0].body
logged: Final = eventually(
lambda: read_rows(
'SELECT call_type, spend, model_group FROM "LiteLLM_SpendLogs" WHERE api_key=%s', (digest,)
),
lambda rows: len(rows) == 1,
seconds=70,
)
assert [(row["call_type"], row["model_group"]) for row in logged] == [("acreate_container", model)], logged
assert float(str(logged[0]["spend"])) == pytest.approx(CODE_INTERPRETER_SESSION_COST), logged
eventually(
lambda: read_rows('SELECT spend FROM "LiteLLM_VerificationToken" WHERE token=%s', (digest,)),
lambda rows: float(str(rows[0]["spend"])) == pytest.approx(CODE_INTERPRETER_SESSION_COST),
seconds=70,
)