Files
firebase-ios-sdk/GeminiLanguageModel/Tests/GeminiLanguageModelTests
Andrew Heard c2186eaa52 fix(ai): attach signature-only reasoning to a part with data (#16886)
Gemini 3.x models return the thought signature of a text response on a
trailing empty text part. The executor records this as a signature-only
`.reasoning` transcript entry, which `GeminiTranscriptTranslator` then
round-tripped on the next turn as a stand-alone `Part` containing only
`thought` and `thoughtSignature` and no `data`.

The Gemini Developer API tolerates a part with no data, but the Gemini
Enterprise Agent Platform rejects it nondeterministically with
`400 INVALID_ARGUMENT` ("Request contains an invalid argument."),
making any multi-turn session that follows a completed text response
flaky on that backend (e.g. `sessionRespondSequentialToolCalls`).

Never emit a signature-only reasoning entry as a data-less part:

- A signature preceding a response is attached to the response's text
  part.
- A signature following a response is attached to the last part of the
  current model turn, mirroring how the server originally sent it.
- If there is no model part to attach to, fall back to a thought part
  with empty text so the `data` oneof is always populated.

Replace the unit test that asserted the data-less shape with coverage
for all three cases.
2026-10-09 21:51:04 -07:00
..

GeminiLanguageModel Tests

Unit and integration test suites validating GeminiLanguageModel protocol conformance, streaming response generation, transcript translation, error mapping, and backend integration.

Quick Start

# Run all unit tests (fast, ~0.04s, skips integration tests)
swift test --skip Integration

# Run all tests in this target (including integration tests)
swift test --filter GeminiLanguageModelTests

Test Suites

Suite / File Scope Strategy
GeminiLanguageModelTests.swift Protocol conformance, single/multi-turn responses, streaming, tool calling Unit (MockHTTPURLProtocol)
GenerationSchema+GeminiTests.swift JSON Schema encoding and property ordering conversion Unit (pure transformation)
GeminiRequestTranslatorTests.swift Request, generation config, tool declarations, and tool mode mapping Unit (pure transformation)
GeminiTranscriptTranslatorTests.swift Apple Transcript <-> Gemini payload mapping (tools, reasoning, prompts) Unit (pure transformation)
GeminiErrorMapperTests.swift HTTP and API error mapping to LanguageModelError Unit (exhaustive mapping)
IntegrationTestingBackendTests.swift Endpoint resolution and credential discovery Unit / Infrastructure
IntegrationTests/ End-to-end Gemini and Firebase AI Logic integration tests Integration (see IntegrationTests/README.md)

Testing Architecture

This target separates tests into two distinct tiers:

  1. Unit Tests (Default):

    • Use MockHTTPURLProtocol for deterministic, zero-network, sub-second execution.
    • Run cleanly in offline, CI, and local development environments without any credentials or background daemons.
  2. Integration Tests (IntegrationTests/):

    • Tagged with .tags(.integration) and gated by .requireIntegrationTestingBackend.
    • Exercise endpoints on Google Cloud and Firebase using configured credentials.
    • Isolated in the IntegrationTests/ subfolder so unit test runs are never slowed down by network timeouts or external dependencies.

Tip

For details on configuring credentials and parameterizing integration tests, see the Integration Tests Guide.