Skip to content

test(ai): run Live API tests on Gemini 3.8 Live - #17044

Open
andrewheard wants to merge 2 commits into
mainfrom
ah/ai-gemini-3.8-live-testing
Open

andrewheard wants to merge 2 commits into
mainfrom
ah/ai-gemini-3.8-live-testing

Conversation

@andrewheard

@andrewheard andrewheard commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Runs LiveSessionTests against gemini-3.8-live in addition to the Gemini 2.5 Live models, and fixes problems that made the suite hang or skip closing sessions. This is part of evaluating Gemini 3.8 Live support for #17031.

Changes

Gemini 3.8 Live coverage

  • Added gemini-3.8-live to the shared arguments, so every test that uses them also runs on 3.8 on both backends. (realtime_voiceActivity was already 3.8-only.)
  • realtime_functionCalling_cancellation now runs on 3.8 on Agent Platform too. Agent Platform is still skipped for 2.5 because of the existing b/450982184 TODO about function IDs.

Closing sessions

  • Added a LiveGenerativeModel.withSession(sessionResumption:_:) test helper. It connects a session, runs the closure, and closes the session whether the closure returns or throws, including when a #require fails. Every test now uses it.
  • Before this, any test that failed before its final close() skipped it. realtime_interruption never called close(), and its retry loop could open up to three sessions per test case. realtime_manual_sessionResumption and realtime_sessionResumption_disabled replaced their first session without closing it. Combined with the deinit issue under Follow-ups, these likely left sessions connected.
  • realtime_manual_sessionResumption now closes the first session before resuming it. Gemini 3.8 Live rejects a resumption handle while its session is still connected ("BidiGenerateContent session is already connected to an existing client").
  • realtime_sessionResumption_disabled now waits for a session handle before closing its first session. Otherwise the message might never be sent, and the test would pass without checking anything.
  • Both resumption tests now fail, instead of passing silently, if the server never sends a session handle.

Timeouts

  • Each test now has .timeLimit(.minutes(1)). Before, a hung test could stall the job until GitHub Actions' 6-hour job timeout: the job sets no timeout-minutes, and Xcode test timeouts aren't enabled.
  • The limit is set on each test rather than on the suite. timeLimit(_:) requires iOS 16, the IntegrationTests-SPM target's deployment target is iOS 15, and Swift Testing doesn't allow @available on a suite.
  • Waiting for a function call cancellation now times out after 10 seconds. Before, it waited indefinitely.
  • Each realtime_interruption attempt now times out after 10 seconds, so all three retries fit in the time limit. The test also now fails if the response stream ends without an interruption; before, it passed.
  • sendVideoRealtime_receiveAudioOutputTranscripts now waits up to 10 seconds for a response instead of 5. In my local runs, every failure of this test was a reply that took longer than 5 seconds.

Gemini 3.8 behavior

  • Added endOfSpeechSilence (3 seconds of silence), which replaces the old padding in the audio, video and interruption tests. Gemini 3.8 Live needs more than one second of silence to detect that the user has stopped speaking. Without it, the 3.8 audio and video tests timed out every time, and realtime_interruption hung on Agent Platform.
  • realtime_interruption now asks the model to count slowly. With the longer silence, Gemini 2.5 finished its one-word reply before the interrupting audio arrived, so the test failed every time.

Known issues

Recorded with withKnownIssue, only for Gemini 3.8 Live and only around the assertions that fail:

  • realtime_functionCalling_cancellation: Gemini 3.8 Live calls functions with NON_BLOCKING behavior by default and only cancels BLOCKING calls automatically (AI Studio migration guide, Agent Platform guide). The SDK can't set FunctionDeclaration.behavior yet. Only the missing cancellation is a known issue: a cancellation with the wrong IDs still fails. It isn't marked intermittent, so Swift Testing will flag it if 3.8 starts sending cancellations.
  • realtime_automaticActivityDetection_disabled: Gemini 3.8 Live sometimes counts 3 or 4 "Hello"s instead of 2. This one is marked intermittent. The test still fails if the model doesn't reply, or replies with something other than a number.

Testing

I ran LiveSessionTests locally against both backends, on an iPhone 18 Pro simulator (iOS 27.2) with Xcode 27.3. CI uses Xcode 26.2; the Swift Testing APIs used here are available in Swift 6.0. Latest full run:

Result Tests
✅ Passed sendAudioRealtime_…, sendVideoRealtime_…, realtime_functionCalling, realtime_sessionResumption_disabled, realtime_interruption, incremental_works, realtime_speechConfig, realtime_voiceActivity
⚠️ Passed with known issues (3.8 only) realtime_functionCalling_cancellation, realtime_automaticActivityDetection_disabled
❌ Failed realtime_manual_sessionResumption and realtime_resumeSession (Google AI 3.8: no reply after resuming); realtime_automaticActivityDetection_enabled (Agent Platform 2.5: counted 3, expected 1)

Remaining flakiness:

  • No reply after resuming a session: the resumption tests occasionally get no reply to "What is my name?" after the session resumes. Across my last four full runs, realtime_resumeSession failed this way on Google AI 3.8 three times and on Google AI 2.5 once, and realtime_manual_sessionResumption failed once on Google AI 3.8. A separate run of 12 iterations per test had one failure in each, on Google AI 3.8 and Agent Platform 2.5. Raising the wait from 5 to 10 seconds didn't help: passing cases reply within a few seconds, and failing cases don't reply at all, so I left the default timeout. Neither failure appears in the two CI logs I checked (the November 9 nightly on main and fix(ai): replace Mutex to fix crash on iOS < 18 #17024), but CI's retries may hide it.
  • realtime_automaticActivityDetection_enabled miscounts on both models: Agent Platform 2.5 miscounted in three of my four full runs, and Google AI 3.8 in one. The "count the hellos" prompts look unreliable in general, so I didn't add a 3.8-only known issue. Rewriting the two counting tests would be a separate change.

Follow-ups

  • SDK fix: a LiveSession released without calling close() probably keeps its WebSocket open. LiveSession.close() is documented as running automatically on deinit, but LiveSessionService's responsesTask and messageQueueTask, and the receive loop in AsyncWebSocket, hold strong references until they're cancelled. That likely stops deinit from ever running. I'll fix that in a separate PR, with a unit test and a CHANGELOG entry.
  • Drop Gemini 2.5: remove the 2.5 models from arguments once they're retired.

#no-changelog

Run every LiveSessionTests case against gemini-3.8-live as well as the
Gemini 2.5 Live models, ahead of the 2.5 retirement, and fix problems
that made the suite hang or leave sessions connected.

- Close every session, even when a test fails, with a new withSession
  helper. Failing tests previously left their sessions connected, and
  two resumption tests left their first session open on every run.
- Close the first session before resuming it. Gemini 3.x Live models
  reject a resumption handle while its session is still connected.
- Add a one-minute time limit to each test, and a timeout while
  waiting for a function call cancellation, so a hung test fails
  instead of stalling the job.
- Send three seconds of silence after speech. Gemini 3.x Live models
  need more than one second of silence to detect the end of speech.
- Ask the model to count slowly in the interruption test, so that its
  response is long enough to interrupt.
- Wait up to 10 seconds for responses to video input.
- Record known issues for Gemini 3.8 Live, which doesn't cancel
  non-blocking function calls and sometimes miscounts when automatic
  activity detection is disabled.
@gemini-code-assist

Copy link
Copy Markdown
Contributor
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Address review feedback on the Gemini 3.8 Live test changes.

- Fail, instead of passing silently, when a resumption test doesn't
  receive a session handle. This also removes the String?? workaround
  in realtime_resumeSession.
- Limit the cancellation known issue to the missing cancellation, so a
  cancellation with the wrong IDs or a dropped connection still fails
  on Gemini 3.8 Live. Move the timed wait into a
  tryCollectNextToolCallCancellation() helper.
- Require a numeric reply in
  realtime_automaticActivityDetection_disabled before applying the
  miscount known issue, so an unrelated reply still fails.
- Time out each realtime_interruption attempt after 10 seconds, so all
  three retries fit within the one-minute limit, and fail if the
  response stream ends without an interruption instead of passing.
- Remove the repeated availability comments, a double blank line, and
  a DocC link that doesn't resolve, and rewrap a comment that was over
  100 columns.
@andrewheard
andrewheard marked this pull request as ready for review November 11, 2026 01:25

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant