Python 88.3%
TypeScript 7.6%
Shell 4.1%
1"""Smoke tests for POST /v1beta/models/{model}:generateContent (gemini-3.5-flash-lite, maxOutputTokens <= 32).23Verified live 2026-09-18. Each test < $0.0001. Paced for the free tier (see _core_helpers.call).4"""5from __future__ import annotations67from tests.gemini._core_helpers import call, gc, text_of, user8910def test_minimal_shape(gemini, models):11 st, body, hdrs = call(gemini, "POST", gc(models["gemini"]), {"contents": user("Reply with OK."), "generationConfig": {"maxOutputTokens": 16}}, note="test_generate_content minimal")12 assert st == 200, body13 c = body["candidates"][0]14 assert c["finishReason"] == "STOP" and c["index"] == 0 and c["content"]["role"] == "model"15 assert "OK" in text_of(body)16 assert c["content"]["parts"][-1].get("thoughtSignature"), "Gemini 3 attaches a thoughtSignature to the last part"17 u = body["usageMetadata"]18 assert {"promptTokenCount", "candidatesTokenCount", "totalTokenCount", "promptTokensDetails", "serviceTier"} <= u.keys()19 assert u["serviceTier"] == "standard" and u["promptTokensDetails"][0]["modality"] == "TEXT"20 assert body["modelVersion"] == models["gemini"] and body["responseId"]212223def test_system_instruction_and_multiturn(gemini, models):24 body = {"systemInstruction": {"parts": [{"text": "Answer with one word."}]},25 "contents": [{"role": "user", "parts": [{"text": "My name is Atlas."}]}, {"role": "model", "parts": [{"text": "Noted."}]}, {"role": "user", "parts": [{"text": "What is my name?"}]}],26 "generationConfig": {"maxOutputTokens": 16, "temperature": 1.0, "topP": 0.95, "topK": 64, "seed": 7, "stopSequences": ["STOP"]}}27 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), body, note="test_generate_content system+multiturn")28 assert st == 200, resp29 assert "atlas" in text_of(resp).lower()303132def test_snake_case_aliases_accepted(gemini, models):33 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), {"system_instruction": {"parts": [{"text": "Answer with OK."}]}, "contents": user("Hi"), "generation_config": {"max_output_tokens": 8}}, note="test_generate_content snake_case")34 assert st == 200, resp353637def test_model_turn_last_rejected(gemini, models):38 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), {"contents": [{"role": "model", "parts": [{"text": "hi"}]}], "generationConfig": {"maxOutputTokens": 8}}, note="test_generate_content model-last")39 assert st == 400 and resp["error"]["status"] == "INVALID_ARGUMENT"40 assert "model turn" in resp["error"]["message"]414243def test_validation_errors_verbatim(gemini, models):44 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), {"contents": user("x"), "generationConfig": {"maxOutputTokens": 8, "temperature": 2.5}}, note="test_generate_content temperature range")45 assert st == 400 and "temperature must be in the range [0.0, 2.0]" in resp["error"]["message"]46 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), {"contents": user("x"), "generationConfig": {"maxOutputTokens": 8, "bogusField": 1}}, note="test_generate_content unknown field")47 assert st == 400 and 'Unknown name "bogusField"' in resp["error"]["message"]48 assert resp["error"]["details"][0]["@type"].endswith("google.rpc.BadRequest")495051def test_unsupported_features_on_gemini3(gemini, models):52 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), {"contents": user("Reply with OK."), "generationConfig": {"maxOutputTokens": 8, "candidateCount": 2}}, note="test_generate_content candidateCount 2")53 assert st == 400 and "Multiple candidates is not enabled" in resp["error"]["message"]54 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), {"contents": user("Reply with OK."), "generationConfig": {"maxOutputTokens": 8, "responseLogprobs": True, "logprobs": 2}}, note="test_generate_content logprobs")55 assert st == 400 and "Logprobs is not enabled" in resp["error"]["message"]565758def test_max_tokens_finish_reason(gemini, models):59 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), {"contents": user("Write a 300 word essay about rivers."), "generationConfig": {"maxOutputTokens": 8}}, note="test_generate_content MAX_TOKENS")60 assert st == 200 and resp["candidates"][0]["finishReason"] == "MAX_TOKENS"616263def test_service_tier_echo(gemini, models):64 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), {"contents": user("Reply with OK."), "serviceTier": "standard", "labels": {"env": "atlas-test"}, "generationConfig": {"maxOutputTokens": 8}}, note="test_generate_content serviceTier")65 assert st == 200 and resp["usageMetadata"]["serviceTier"] == "standard"666768def test_safety_ratings_present_when_settings_sent(gemini, models):69 cats = ["HARM_CATEGORY_HARASSMENT", "HARM_CATEGORY_HATE_SPEECH", "HARM_CATEGORY_SEXUALLY_EXPLICIT", "HARM_CATEGORY_DANGEROUS_CONTENT"]70 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), {"contents": user("Reply with OK."), "safetySettings": [{"category": c, "threshold": "BLOCK_LOW_AND_ABOVE"} for c in cats], "generationConfig": {"maxOutputTokens": 8}}, note="test_generate_content safety")71 assert st == 200, resp72 ratings = resp["candidates"][0]["safetyRatings"]73 assert {r["category"] for r in ratings} == set(cats) and all(r["probability"] in ("NEGLIGIBLE", "LOW", "MEDIUM", "HIGH") for r in ratings)74 st, resp, _ = call(gemini, "POST", gc(models["gemini"]), {"contents": user("x"), "safetySettings": [{"category": "HARM_CATEGORY_TOXICITY", "threshold": "BLOCK_NONE"}], "generationConfig": {"maxOutputTokens": 8}}, note="test_generate_content PaLM category")75 assert st == 400 and "element predicate failed" in resp["error"]["message"]767778def test_unknown_model_404(gemini):79 st, resp, _ = call(gemini, "POST", gc("gemini-99-ultra"), {"contents": user("x")}, note="test_generate_content 404")80 assert st == 404 and resp["error"]["status"] == "NOT_FOUND" and "ListModels" in resp["error"]["message"]81