litellm/tests/e2e/llm_translation/test_image_generation_e2e.py
mubashir1osmani ec8088f064
test(e2e): vendor API testing coverage (#34557)
* test(e2e): cover vendor strategy gaps for chat contract, image edits, auth, team activity

Resolves the first slice of LIT-4778 (vendor API testing strategy): image edits happy path, chat multi-turn + validation + sanitization, LLM-route auth header matrix, and /team/daily/activity structure

* test(e2e): expand vendor API strategy coverage across endpoints

Adds validation cases on existing endpoint suites, plus vector stores, search,
bedrock native, realtime HTTP secrets/calls, responses retrieve, files/batches
contract, and chat stream SSE. Registers coverage cells for LIT-4778

* test(e2e): finish vendor strategy open items

Audio transcription negatives, vector-store file attach/poll/search,
OpenAI moderation category matrix across chat/messages/responses, and
smoke model matrix for chat (LIT-4778)

* test(e2e): harden vendor strategy suite against live env edges

Fix stream [DONE] tracking, XSS no-crash contract, realtime model routing,
vector store list/search models, responses validation, and provider-denied
Bedrock paths so the suite is stable against a live proxy

* test(e2e): rename suites, drop vendor_contract, fix greptile gaps

Move shared status helpers into e2e_http, rename chat auth headers and
chat security suites, remove vendor_contract and dev_config files_settings,
and tighten transcription validation plus vector-store search assertions

* test(e2e): route bedrock stream disconnects through e2e_http

Catch mid-stream RequestException in the shared harness so bedrock native
tests do not import requests directly
2026-08-12 01:07:52 +00:00

130 lines
5.4 KiB
Python

"""Live e2e: POST /v1/images/generations returns an image.
Registers an OpenAI image deployment at runtime and asserts the response carries a
generated image (url or base64). Migrated from
litellm-regression-tests/tests/test_inference_endpoints.py.
"""
from __future__ import annotations
import pytest
from e2e_config import unique_marker
from e2e_http import (
assert_client_error,
require_successful_call,
)
from endpoints_client import EndpointsClient, ImagesResult
from lifecycle import ResourceManager
from models import LiteLLMParamsBody
from pydantic import BaseModel
pytestmark = pytest.mark.e2e
class _OptionalImageBody(BaseModel):
model: str | None = None
prompt: str | None = None
n: int | None = None
size: str | None = None
def _assert_image_returned(body: str) -> None:
parsed = ImagesResult.model_validate_json(body)
assert parsed.data, f"/images/generations returned no data: {body[:300]}"
first = parsed.data[0]
assert first.b64_json or first.url, (
f"generated image has neither b64_json nor url: {body[:300]}"
)
def _register_openai_image(
endpoints_client: EndpointsClient, resources: ResourceManager
) -> tuple[str, str]:
model = f"e2e-image-{unique_marker()}"
model_id = endpoints_client.create_model(
model,
LiteLLMParamsBody(model="openai/gpt-image-1-mini", api_key="os.environ/OPENAI_API_KEY"),
)
resources.defer(lambda: endpoints_client.delete_model(model_id))
return model, resources.key()
class TestImageGeneration:
@pytest.mark.covers("llm.images_generations.openai.basic.nonstream.works")
def test_image_generation_returns_image(
self, endpoints_client: EndpointsClient, resources: ResourceManager
) -> None:
model, key = _register_openai_image(endpoints_client, resources)
result = endpoints_client.images(key, model, "Draw a cute cat")
require_successful_call(result)
_assert_image_returned(result.body)
@pytest.mark.covers("llm.images_generations.bedrock.basic.nonstream.works", exercised_on=["images_generations"])
def test_bedrock_image_generation_returns_image(
self, endpoints_client: EndpointsClient, resources: ResourceManager
) -> None:
model = f"e2e-bedrock-image-{unique_marker()}"
model_id = endpoints_client.create_model(
model,
LiteLLMParamsBody(
model="bedrock/amazon.nova-canvas-v1:0",
aws_access_key_id="os.environ/AWS_ACCESS_KEY_ID",
aws_secret_access_key="os.environ/AWS_SECRET_ACCESS_KEY",
aws_region_name="os.environ/AWS_REGION",
),
)
resources.defer(lambda: endpoints_client.delete_model(model_id))
key = resources.key()
result = endpoints_client.images(key, model, "Draw a cute cat")
require_successful_call(result)
_assert_image_returned(result.body)
@pytest.mark.skip(reason="stage red: product gap, /v1/images/generations 500s (aimage_generation TypeError) on missing prompt instead of 400")
@pytest.mark.covers("llm.images_generations.openai.input_validation.nonstream.works")
def test_missing_prompt_returns_error(
self, endpoints_client: EndpointsClient, resources: ResourceManager
) -> None:
model, key = _register_openai_image(endpoints_client, resources)
result = endpoints_client.proxy.transport.send(
"/v1/images/generations",
headers=endpoints_client.proxy.transport.bearer(key),
json=_OptionalImageBody(model=model),
)
assert_client_error(result, "images missing prompt")
@pytest.mark.covers("llm.images_generations.openai.input_validation.nonstream.works")
def test_empty_prompt_returns_client_error(
self, endpoints_client: EndpointsClient, resources: ResourceManager
) -> None:
model, key = _register_openai_image(endpoints_client, resources)
result = endpoints_client.proxy.transport.send(
"/v1/images/generations",
headers=endpoints_client.proxy.transport.bearer(key),
json=_OptionalImageBody(model=model, prompt=""),
)
assert_client_error(result, "images empty prompt")
@pytest.mark.covers("llm.images_generations.openai.input_validation.nonstream.works")
def test_invalid_size_returns_client_error(
self, endpoints_client: EndpointsClient, resources: ResourceManager
) -> None:
model, key = _register_openai_image(endpoints_client, resources)
result = endpoints_client.proxy.transport.send(
"/v1/images/generations",
headers=endpoints_client.proxy.transport.bearer(key),
json=_OptionalImageBody(model=model, prompt="a blue square", size="999x999"),
)
assert_client_error(result, "images invalid size")
@pytest.mark.covers("llm.images_generations.openai.input_validation.nonstream.works")
def test_invalid_n_returns_client_error(
self, endpoints_client: EndpointsClient, resources: ResourceManager
) -> None:
model, key = _register_openai_image(endpoints_client, resources)
result = endpoints_client.proxy.transport.send(
"/v1/images/generations",
headers=endpoints_client.proxy.transport.bearer(key),
json=_OptionalImageBody(model=model, prompt="a blue square", n=0),
)
assert_client_error(result, "images invalid n")