Skip to content

[AI] LiveSession WebSocket leak fixes#16137

Draft
andrewheard wants to merge 7 commits into
mainfrom
ah/ai-live-api-investigation
Draft

[AI] LiveSession WebSocket leak fixes#16137
andrewheard wants to merge 7 commits into
mainfrom
ah/ai-live-api-investigation

Conversation

@andrewheard
Copy link
Copy Markdown
Contributor

@andrewheard andrewheard commented Apr 29, 2026

LiveSession Socket Leak Analysis

Executive Summary

Investigation into the flakiness of LiveSessionTests and the recurring setsockopt SO_CONNECTION_IDLE failed logs revealed multiple strong reference cycles in the LiveSession implementation. These cycles prevent the deinitialization of WebSocket components when a session is dropped (especially during test failures), leading to leaked connections and unstable network behavior on CI.

Identified Reference Cycles

1. AsyncWebSocket Receiving Task Cycle

In AsyncWebSocket.swift, the startReceiving() method launches a Task that captures self strongly:

// AsyncWebSocket.swift
private func startReceiving() {
  Task {
    while !Task.isCancelled && self.webSocketTask.isOpen && self.closeError.value() == nil {
      // ... captures self strongly ...
    }
  }
}

Impact: AsyncWebSocket is held alive by this background task as long as the socket is not explicitly closed. Since deinit is responsible for calling disconnect() (which would stop the task), the object becomes un-releasable if the user forgets to call close().

2. LiveSessionService Actor Task Cycles

The LiveSessionService actor manages two long-running tasks that capture the actor reference strongly:

// LiveSessionService.swift
responsesTask = Task {
  do {
    for try await message in stream {
      // ... captures self (actor) ...
    }
  } catch {
    if let error = mapWebsocketError(error) {
      close() // Method call captures self
      // ...
    }
  }
}

Impact: The actor cannot be deinitialized as long as responsesTask or messageQueueTask are active. These tasks only terminate when the stream finishes or they are cancelled. However, cancellation typically happens in deinit, which is blocked by the tasks themselves.

3. Missing LiveSession Cleanup

LiveSession.swift acts as the public interface but lacks a deinit mechanism to ensure the underlying service is closed if the session object is dropped.

Impact on Integration Tests

In LiveSessionTests.swift, many tests follow this pattern:

let session = try await model.connect()
// ... some async operations that might throw ...
await session.close()

If any operation before session.close() throws an error (which is common in flaky CI environments), the close() call is skipped. Due to the reference cycles identified above, the dropped session object fails to clean up its LiveSessionService and AsyncWebSocket, resulting in a leaked WebSocket connection.

Accumulated leaks on CI likely lead to:

  • Exhaustion of file descriptors or network resources.
  • Interference between tests sharing the same URLSession.
  • System warnings like setsockopt SO_CONNECTION_IDLE failed [42: Protocol not available] as the OS attempts to manage orphaned connections.
  • Connection Hangs: Dead connections can go undetected for several minutes (e.g., 4 minutes) before the OS finally reports a "Socket is not connected" error, leading to long test durations on CI.

Technical Cause of Hangs

  1. Lack of Pings: URLSessionWebSocketTask does not send pings automatically. Without pings, neither the client nor the server can quickly detect if the other side has silently dropped the connection.
  2. Incomplete Error Propagation: In LiveSessionService, if a WebSocket closes normally (or is mapped to a "normal" closure like .goingAway), the internal responseContinuation was not being finished, causing any code awaiting session.responses to hang indefinitely.
  3. Inaccurate Error Capture: AsyncWebSocket was checking task.error instead of the error caught from receive(), which sometimes led to losing the specific error code (like POSIX 57).

Applied Fixes

  • Weak References: Replaced strong captures of self with [weak self] in all background Task closures within AsyncWebSocket and LiveSessionService.
  • Explicit Deinit Cleanup: Added a deinit to LiveSession that spawns a non-blocking task to call service.close().
  • Test Robustness: Updated LiveSessionTests.swift to consistently use do-catch blocks around session operations.
  • WebSocket Pings: Implemented a 30-second ping interval in AsyncWebSocket to detect dead connections.
  • Improved Error Handling: Refined error mapping and propagation to ensure all closures (normal or otherwise) are signaled to the user, and preserved original error context from `URLSession.
  • Resumable Streams: Refactored LiveSessionService.close() to allow closing the WebSocket connection without terminating the public responses stream. This allows the stream to survive connection resets (like during resumeSession()) and seamlessly receive messages from the new connection, fixing a regression where resumed sessions would return empty responses.

#no-changelog

@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

Customization

To customize 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 counter productive. 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.

@andrewheard
Copy link
Copy Markdown
Contributor Author

Although the Live API tests still failed, the logs were much more readable with most of the sockets being cleaned up.

xcodebuild-test-without-building.log
Command line invocation:
    /Applications/Xcode_26.2.app/Contents/Developer/usr/bin/xcodebuild -project FirebaseAI/Tests/TestApp/FirebaseAITestApp.xcodeproj -scheme FirebaseAITestApp-SPM -destination "platform=iOS Simulator,name=iPhone 17" ONLY_ACTIVE_ARCH=YES CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=YES COMPILER_INDEX_STORE_ENABLE=NO -parallel-testing-enabled NO -retry-tests-on-failure -test-iterations 3 test-without-building

Build settings from command line:
    CODE_SIGNING_ALLOWED = YES
    CODE_SIGNING_REQUIRED = NO
    COMPILER_INDEX_STORE_ENABLE = NO
    ONLY_ACTIVE_ARCH = YES

Retrying tests on failure. Running tests repeatedly up to 3 times.

Resolve Package Graph


Resolved source packages:
  GoogleDataTransport: https://github.com/google/GoogleDataTransport.git @ 10.1.0
  abseil: https://github.com/google/abseil-cpp-binary.git @ 1.2024072200.0
  GTMSessionFetcher: https://github.com/google/gtm-session-fetcher.git @ 5.2.0
  Promises: https://github.com/google/promises.git @ 2.4.0
  Firebase: /Users/runner/work/firebase-ios-sdk/firebase-ios-sdk @ local
  InteropForGoogle: https://github.com/google/interop-ios-for-google-sdks.git @ 101.0.0
  GoogleAdsOnDeviceConversion: https://github.com/googleads/google-ads-on-device-conversion-ios-sdk @ 3.5.0
  leveldb: https://github.com/firebase/leveldb.git @ 1.22.5
  nanopb: https://github.com/firebase/nanopb.git @ 2.30910.0
  AppCheck: https://github.com/google/app-check.git @ 11.2.0
  GoogleAppMeasurement: https://github.com/google/GoogleAppMeasurement.git @ main (c2c76be)
  gRPC: https://github.com/google/grpc-binary.git @ 1.69.1
  GoogleUtilities: https://github.com/google/GoogleUtilities.git @ 8.1.0

--- xcodebuild: WARNING: Using the first of multiple matching destinations:
{ platform:iOS Simulator, arch:arm64, id:40880212-E959-4999-88DE-3F7F1D5E520A, OS:26.4.1, name:iPhone 17 }
{ platform:iOS Simulator, arch:x86_64, id:40880212-E959-4999-88DE-3F7F1D5E520A, OS:26.4.1, name:iPhone 17 }
Testing started
2026-04-29 17:43:13.867690+0000 FirebaseAITestApp-SPM[12012:41388] [General] Failed to send CA Event for app launch measurements for ca_event_type: 0 event_name: com.apple.app_launch_measurement.FirstFramePresentationMetric
2026-04-29 17:43:13.963663+0000 FirebaseAITestApp-SPM[12012:41387] [General] Failed to send CA Event for app launch measurements for ca_event_type: 1 event_name: com.apple.app_launch_measurement.ExtendedLaunchMetrics
Test Suite 'All tests' started at 2026-04-29 17:43:26.928.
Test Suite 'IntegrationTests-SPM.xctest' started at 2026-04-29 17:43:26.929.
Test Suite 'IntegrationTests' started at 2026-04-29 17:43:26.929.
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_appCheckNotConfigured_shouldFail]' started (Iteration 1 of 3).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_appCheckNotConfigured_shouldFail]' passed (1.740 seconds).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_functionCalling]' started (Iteration 1 of 3).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_functionCalling]' passed (0.330 seconds).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_image_fileData_public]' started (Iteration 1 of 3).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_image_fileData_public]' passed (0.577 seconds).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_image_fileData_requiresAuth_signedIn]' started (Iteration 1 of 3).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_image_fileData_requiresAuth_signedIn]' passed (0.499 seconds).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_image_fileData_requiresUserAuth_userSignedIn]' started (Iteration 1 of 3).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_image_fileData_requiresUserAuth_userSignedIn]' passed (0.467 seconds).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_image_fileData_requiresUserAuth_wrongUser_permissionDenied]' started (Iteration 1 of 3).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_image_fileData_requiresUserAuth_wrongUser_permissionDenied]' passed (4.262 seconds).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_image_inlineData]' started (Iteration 1 of 3).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_image_inlineData]' passed (0.302 seconds).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_text]' started (Iteration 1 of 3).
Test Case '-[IntegrationTests_SPM.IntegrationTests testCountTokens_text]' passed (0.206 seconds).
Test Suite 'IntegrationTests' passed at 2026-04-29 17:43:35.316.
	 Executed 8 tests, with 0 failures (0 unexpected) in 8.384 (8.387) seconds
Test Suite 'IntegrationTests-SPM.xctest' passed at 2026-04-29 17:43:35.317.
	 Executed 8 tests, with 0 failures (0 unexpected) in 8.384 (8.388) seconds
Test Suite 'All tests' passed at 2026-04-29 17:43:35.317.
	 Executed 8 tests, with 0 failures (0 unexpected) in 8.384 (8.389) seconds
◇ Test run started.
↳ Testing Library Version: 1501
↳ Target Platform: arm64-apple-ios13.0-simulator
◇ Iteration 1 started.
◇ Suite CountTokensIntegrationTests started.
◇ Test countTokens_text(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to countTokens_text(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to countTokens_text(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to countTokens_text(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to countTokens_text(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to countTokens_text(_:) started.
​✔ Test countTokens_text(_:) with 5 test cases passed after 1.901 seconds.
◇ Test countTokens_text_systemInstruction(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to countTokens_text_systemInstruction(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to countTokens_text_systemInstruction(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to countTokens_text_systemInstruction(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to countTokens_text_systemInstruction(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to countTokens_text_systemInstruction(_:) started.
​✔ Test countTokens_text_systemInstruction(_:) with 5 test cases passed after 1.660 seconds.
◇ Test countTokens_jsonSchema(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to countTokens_jsonSchema(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to countTokens_jsonSchema(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to countTokens_jsonSchema(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to countTokens_jsonSchema(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to countTokens_jsonSchema(_:) started.
​✔ Test countTokens_jsonSchema(_:) with 5 test cases passed after 1.536 seconds.
✔ Suite CountTokensIntegrationTests passed after 5.104 seconds.
◇ Suite GenerateContentIntegrationTests started.
◇ Test generateContent(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-2.5-flash-lite" to generateContent(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-flash-lite" to generateContent(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global) - FAC Limited-Use, modelName → "gemini-2.5-flash-lite" to generateContent(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview" to generateContent(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-3.1-flash-lite-preview" to generateContent(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemma-4-31b-it" to generateContent(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemma-4-31b-it" to generateContent(_:modelName:) started.
​✔ Test generateContent(_:modelName:) with 7 test cases passed after 9.752 seconds.
◇ Test "Generate an enum and provide a system instruction" started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to "Generate an enum and provide a system instruction" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to "Generate an enum and provide a system instruction" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to "Generate an enum and provide a system instruction" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to "Generate an enum and provide a system instruction" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to "Generate an enum and provide a system instruction" started.
2026-04-29 17:43:37.993819+0000 FirebaseAITestApp-SPM[12012:41390] [[GoogleUtilities/AppDelegateSwizzler]] 12.13.0 - [GoogleUtilities/AppDelegateSwizzler][I-SWZ001014] App Delegate does not conform to UIApplicationDelegate protocol.
​✔ Test "Generate an enum and provide a system instruction" with 5 test cases passed after 8.788 seconds.
◇ Test generateContentThinking(_:modelName:thinkingConfig:) started.
◇ Test case passing 3 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-2.5-flash", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(0), thinkingLevel: nil, includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-2.5-flash", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(24576), thinkingLevel: nil, includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-2.5-flash", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(24576), thinkingLevel: nil, includeThoughts: Optional(true)) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-pro", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(128), thinkingLevel: nil, includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-pro", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(32768), thinkingLevel: nil, includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-pro", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(32768), thinkingLevel: nil, includeThoughts: Optional(true)) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(0), thinkingLevel: nil, includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(24576), thinkingLevel: nil, includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(24576), thinkingLevel: nil, includeThoughts: Optional(true)) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-2.5-pro", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(128), thinkingLevel: nil, includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-2.5-pro", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(32768), thinkingLevel: nil, includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-2.5-pro", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(32768), thinkingLevel: nil, includeThoughts: Optional(true)) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview", thinkingConfig → ThinkingConfig(thinkingBudget: nil, thinkingLevel: Optional(FirebaseAILogic.ThinkingConfig.ThinkingLevel(rawValue: "MINIMAL")), includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview", thinkingConfig → ThinkingConfig(thinkingBudget: nil, thinkingLevel: Optional(FirebaseAILogic.ThinkingConfig.ThinkingLevel(rawValue: "LOW")), includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview", thinkingConfig → ThinkingConfig(thinkingBudget: nil, thinkingLevel: Optional(FirebaseAILogic.ThinkingConfig.ThinkingLevel(rawValue: "MEDIUM")), includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview", thinkingConfig → ThinkingConfig(thinkingBudget: nil, thinkingLevel: Optional(FirebaseAILogic.ThinkingConfig.ThinkingLevel(rawValue: "HIGH")), includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(0), thinkingLevel: nil, includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
2026-04-29 17:43:57.171379+0000 FirebaseAITestApp-SPM[12012:41390] [[FirebaseAppCheck]] 12.13.0 - [FirebaseAppCheck][I-FAA002002] Cannot instantiate `FIRAppCheck` for app: app-check-not-configured without an app check provider. Please make sure the provider factory returns a valid app check provider.
2026-04-29 17:44:44.983685+0000 FirebaseAITestApp-SPM[12012:41390] [[FirebaseAppCheck]] 12.13.0 - [FirebaseAppCheck][I-FAA002002] Cannot instantiate `FIRAppCheck` for app: app-check-not-configured without an app check provider. Please make sure the provider factory returns a valid app check provider.
2026-04-29 17:44:44.995779+0000 FirebaseAITestApp-SPM[12012:41390] [[FirebaseAppCheck]] 12.13.0 - [FirebaseAppCheck][I-FAA002002] Cannot instantiate `FIRAppCheck` for app: app-check-not-configured without an app check provider. Please make sure the provider factory returns a valid app check provider.
2026-04-29 17:44:44.998651+0000 FirebaseAITestApp-SPM[12012:41390] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002001] The server responded with an error: <NSHTTPURLResponse: 0x103a87e00> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/locations/us-central1/publishers/google/models/gemini-2.0-flash:countTokens } { Status Code: 401, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Encoding" =     (
        gzip
    );
    "Content-Length" =     (
        127
    );
    "Content-Type" =     (
        "application/json; charset=UTF-8"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:43:28 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
2026-04-29 17:44:45.001870+0000 FirebaseAITestApp-SPM[12012:41390] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002002] Response payload: {
  "error": {
    "code": 401,
    "message": "Firebase App Check token is invalid.",
    "status": "UNAUTHENTICATED"
  }
}
2026-04-29 17:44:45.005774+0000 FirebaseAITestApp-SPM[12012:41390] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002001] The server responded with an error: <NSHTTPURLResponse: 0x1071f2c60> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/locations/us-central1/publishers/google/models/gemini-2.0-flash:countTokens } { Status Code: 403, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Encoding" =     (
        gzip
    );
    "Content-Length" =     (
        128
    );
    "Content-Type" =     (
        "application/json; charset=UTF-8"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:43:34 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
2026-04-29 17:44:45.007144+0000 FirebaseAITestApp-SPM[12012:41390] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002002] Response payload: {
  "error": {
    "code": 403,
    "message": "The caller does not have permission",
    "status": "PERMISSION_DENIED"
  }
}
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(32768), thinkingLevel: nil, includeThoughts: nil) to generateContentThinking(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(32768), thinkingLevel: nil, includeThoughts: Optional(true)) to generateContentThinking(_:modelName:thinkingConfig:) started.
​✔ Test generateContentThinking(_:modelName:thinkingConfig:) with 19 test cases passed after 60.837 seconds.
◇ Test generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
◇ Test case passing 3 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-flash", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(-1), thinkingLevel: nil, includeThoughts: nil) to generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-flash", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(-1), thinkingLevel: nil, includeThoughts: Optional(true)) to generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-pro", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(-1), thinkingLevel: nil, includeThoughts: nil) to generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-pro", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(-1), thinkingLevel: nil, includeThoughts: Optional(true)) to generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(-1), thinkingLevel: nil, includeThoughts: nil) to generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(-1), thinkingLevel: nil, includeThoughts: Optional(true)) to generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-2.5-pro", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(-1), thinkingLevel: nil, includeThoughts: nil) to generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-2.5-pro", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(-1), thinkingLevel: nil, includeThoughts: Optional(true)) to generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(-1), thinkingLevel: nil, includeThoughts: nil) to generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
​◇ Test case passing 3 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview", thinkingConfig → ThinkingConfig(thinkingBudget: Optional(-1), thinkingLevel: nil, includeThoughts: Optional(true)) to generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) started.
​✔ Test generateContentThinkingFunctionCalling(_:modelName:thinkingConfig:) with 10 test cases passed after 73.816 seconds.
◇ Test generateImageWithAspectRatio(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-2.5-flash-image" to generateImageWithAspectRatio(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-flash-image" to generateImageWithAspectRatio(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-image" to generateImageWithAspectRatio(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-image-preview" to generateImageWithAspectRatio(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-3.1-flash-image-preview" to generateImageWithAspectRatio(_:modelName:) started.
​✔ Test generateImageWithAspectRatio(_:modelName:) with 5 test cases passed after 52.251 seconds.
◇ Test generateImageWithCustomSize(_:modelName:) started.
◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-image-preview" to generateImageWithCustomSize(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-3.1-flash-image-preview" to generateImageWithCustomSize(_:modelName:) started.
​✔ Test generateImageWithCustomSize(_:modelName:) with 2 test cases passed after 70.199 seconds.
◇ Test generateContent_finishReason_imageSafety(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-2.5-flash-image" to generateContent_finishReason_imageSafety(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-flash-image" to generateContent_finishReason_imageSafety(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-image" to generateContent_finishReason_imageSafety(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-image-preview" to generateContent_finishReason_imageSafety(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-3.1-flash-image-preview" to generateContent_finishReason_imageSafety(_:modelName:) started.
​✔ Test generateContent_finishReason_imageSafety(_:modelName:) with 5 test cases passed after 38.397 seconds.
◇ Test generateImage(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-2.5-flash-image" to generateImage(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-flash-image" to generateImage(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-image" to generateImage(_:modelName:) started.
​✔ Test generateImage(_:modelName:) with 3 test cases passed after 19.577 seconds.
◇ Test "generateContent with Google Search returns grounding metadata" started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to "generateContent with Google Search returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to "generateContent with Google Search returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to "generateContent with Google Search returns grounding metadata" started.
2026-04-29 17:49:22.187031+0000 FirebaseAITestApp-SPM[12012:64206] [connection] nw_connection_copy_protocol_metadata_internal_block_invoke [C8] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection
2026-04-29 17:49:22.187669+0000 FirebaseAITestApp-SPM[12012:64206] [connection] nw_connection_copy_protocol_metadata_internal_block_invoke [C8] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection
2026-04-29 17:49:22.187800+0000 FirebaseAITestApp-SPM[12012:64206] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C8] Client called nw_connection_copy_connected_local_endpoint on unconnected nw_connection
2026-04-29 17:49:22.187904+0000 FirebaseAITestApp-SPM[12012:64206] [connection] nw_connection_copy_connected_remote_endpoint_block_invoke [C8] Client called nw_connection_copy_connected_remote_endpoint on unconnected nw_connection
2026-04-29 17:49:22.196318+0000 FirebaseAITestApp-SPM[12012:64206] [] nw_protocol_instance_set_output_handler Not calling remove_input_handler on 0x10706a200:socket
2026-04-29 17:49:22.202194+0000 FirebaseAITestApp-SPM[12012:64206] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C6] Connection has no local endpoint
2026-04-29 17:49:22.204676+0000 FirebaseAITestApp-SPM[12012:64206] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C6] Connection has no local endpoint
​◇ Test case passing 1 argument config → Google AI (v1beta) to "generateContent with Google Search returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to "generateContent with Google Search returns grounding metadata" started.
​✔ Test "generateContent with Google Search returns grounding metadata" with 5 test cases passed after 20.257 seconds.
◇ Test "generateContent with URL Context" started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to "generateContent with URL Context" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to "generateContent with URL Context" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to "generateContent with URL Context" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to "generateContent with URL Context" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to "generateContent with URL Context" started.
​✔ Test "generateContent with URL Context" with 5 test cases passed after 20.700 seconds.
◇ Test generateContent_codeExecution_succeeds(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to generateContent_codeExecution_succeeds(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to generateContent_codeExecution_succeeds(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to generateContent_codeExecution_succeeds(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to generateContent_codeExecution_succeeds(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to generateContent_codeExecution_succeeds(_:) started.
​✔ Test generateContent_codeExecution_succeeds(_:) with 5 test cases passed after 34.206 seconds.
◇ Test generateContentStream(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-2.5-flash-lite" to generateContentStream(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-3.1-flash-lite-preview" to generateContentStream(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global) - FAC Limited-Use, modelName → "gemini-3.1-flash-lite-preview" to generateContentStream(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-lite" to generateContentStream(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-lite" to generateContentStream(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemma-4-31b-it" to generateContentStream(_:modelName:) started.
​✔ Test generateContentStream(_:modelName:) with 6 test cases passed after 13.160 seconds.
◇ Test generateImageStreaming(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-2.5-flash-image" to generateImageStreaming(_:modelName:) started.
2026-04-29 17:50:35.162800+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
2026-04-29 17:50:48.562752+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
2026-04-29 17:50:49.121817+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), modelName → "gemini-2.5-flash-image" to generateImageStreaming(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-image" to generateImageStreaming(_:modelName:) started.
2026-04-29 17:50:49.424668+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
2026-04-29 17:50:58.989357+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
2026-04-29 17:50:59.559164+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
2026-04-29 17:51:00.391200+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
2026-04-29 17:51:01.379359+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
2026-04-29 17:51:01.845852+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
​✔ Test generateImageStreaming(_:modelName:) with 3 test cases passed after 21.165 seconds.
◇ Test generateContent_appCheckNotConfigured_shouldFail(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to generateContent_appCheckNotConfigured_shouldFail(_:) started.
2026-04-29 17:51:02.422889+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) - FAC Limited-Use to generateContent_appCheckNotConfigured_shouldFail(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to generateContent_appCheckNotConfigured_shouldFail(_:) started.
2026-04-29 17:51:03.583531+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from the first candidate.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to generateContent_appCheckNotConfigured_shouldFail(_:) started.
2026-04-29 17:51:03.997422+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002001] The server responded with an error: <NSHTTPURLResponse: 0x1071f0660> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent } { Status Code: 401, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Encoding" =     (
        gzip
    );
    "Content-Length" =     (
        127
    );
    "Content-Type" =     (
        "application/json; charset=UTF-8"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:51:03 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
​✔ Test generateContent_appCheckNotConfigured_shouldFail(_:) with 4 test cases passed after 0.702 seconds.
✔ Suite GenerateContentIntegrationTests passed after 443.819 seconds.
◇ Suite GenerativeModelSessionHybridTests started.
◇ Test respondText_fallbackOnGeminiModelError(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondText_fallbackOnGeminiModelError(_:) started.
2026-04-29 17:51:04.158428+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002002] Response payload: {
  "error": {
    "code": 401,
    "message": "Firebase App Check token is invalid.",
    "status": "UNAUTHENTICATED"
  }
}
2026-04-29 17:51:04.736776+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAppCheck]] 12.13.0 - [FirebaseAppCheck][I-FAA002002] Cannot instantiate `FIRAppCheck` for app: app-check-not-configured without an app check provider. Please make sure the provider factory returns a valid app check provider.
2026-04-29 17:51:04.982109+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002001] The server responded with an error: <NSHTTPURLResponse: 0x1071f0940> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/locations/us-central1/publishers/google/models/gemini-2.5-flash:generateContent } { Status Code: 401, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Encoding" =     (
        gzip
    );
    "Content-Length" =     (
        127
    );
    "Content-Type" =     (
        "application/json; charset=UTF-8"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:51:04 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
2026-04-29 17:51:05.157215+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002002] Response payload: {
  "error": {
    "code": 401,
    "message": "Firebase App Check token is invalid.",
    "status": "UNAUTHENTICATED"
  }
}
2026-04-29 17:51:05.398558+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAppCheck]] 12.13.0 - [FirebaseAppCheck][I-FAA002002] Cannot instantiate `FIRAppCheck` for app: app-check-not-configured without an app check provider. Please make sure the provider factory returns a valid app check provider.
2026-04-29 17:51:05.668773+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002001] The server responded with an error: <NSHTTPURLResponse: 0x1071f1300> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/models/gemini-2.5-flash:generateContent } { Status Code: 401, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Encoding" =     (
        gzip
    );
    "Content-Length" =     (
        127
    );
    "Content-Type" =     (
        "application/json; charset=UTF-8"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:51:04 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
2026-04-29 17:51:06.084776+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002002] Response payload: {
  "error": {
    "code": 401,
    "message": "Firebase App Check token is invalid.",
    "status": "UNAUTHENTICATED"
  }
}
2026-04-29 17:51:06.188532+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAppCheck]] 12.13.0 - [FirebaseAppCheck][I-FAA002002] Cannot instantiate `FIRAppCheck` for app: app-check-not-configured without an app check provider. Please make sure the provider factory returns a valid app check provider.
2026-04-29 17:51:06.359214+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002001] The server responded with an error: <NSHTTPURLResponse: 0x1071f34c0> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/models/gemini-2.5-flash:generateContent } { Status Code: 401, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Encoding" =     (
        gzip
    );
    "Content-Length" =     (
        127
    );
    "Content-Type" =     (
        "application/json; charset=UTF-8"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:51:04 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
2026-04-29 17:51:06.407391+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002002] Response payload: {
  "error": {
    "code": 401,
    "message": "Firebase App Check token is invalid.",
    "status": "UNAUTHENTICATED"
  }
}
2026-04-29 17:51:06.587440+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002001] The server responded with an error: <NSHTTPURLResponse: 0x1071f3460> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name-1:generateContent } { Status Code: 404, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Encoding" =     (
        gzip
    );
    "Content-Length" =     (
        284
    );
    "Content-Type" =     (
        "application/json; charset=UTF-8"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:51:04 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
2026-04-29 17:51:06.704856+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002002] Response payload: {
  "error": {
    "code": 404,
    "message": "Publisher Model `projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name-1` was not found or your project does not have access to it. Please ensure you are using a valid model version. For more information, see: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versions",
    "status": "NOT_FOUND"
  }
}
2026-04-29 17:51:06.918654+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004009] Primary model "invalid-model-name-1" failed with error: internalError(underlying: FirebaseAILogic.BackendError(httpResponseCode: 404, message: "Publisher Model `projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name-1` was not found or your project does not have access to it. Please ensure you are using a valid model version. For more information, see: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versions", status: FirebaseAILogic.RPCStatus.notFound, details: [])); falling back to secondary model "hybrid:invalid-model-name-2,gemini-2.5-flash-lite".
​✔ Test respondText_fallbackOnGeminiModelError(_:) with 1 test case passed after 2.821 seconds.
◇ Test respondText_fallbackOnFoundationModelsError(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondText_fallbackOnFoundationModelsError(_:) started.
2026-04-29 17:51:07.050495+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002001] The server responded with an error: <NSHTTPURLResponse: 0x1071f3760> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name-2:generateContent } { Status Code: 404, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Encoding" =     (
        gzip
    );
    "Content-Length" =     (
        284
    );
    "Content-Type" =     (
        "application/json; charset=UTF-8"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:51:04 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
2026-04-29 17:51:07.750573+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002002] Response payload: {
  "error": {
    "code": 404,
    "message": "Publisher Model `projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name-2` was not found or your project does not have access to it. Please ensure you are using a valid model version. For more information, see: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versions",
    "status": "NOT_FOUND"
  }
}
2026-04-29 17:51:07.813795+0000 FirebaseAITestApp-SPM[12012:82381] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004009] Primary model "invalid-model-name-2" failed with error: internalError(underlying: FirebaseAILogic.BackendError(httpResponseCode: 404, message: "Publisher Model `projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name-2` was not found or your project does not have access to it. Please ensure you are using a valid model version. For more information, see: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versions", status: FirebaseAILogic.RPCStatus.notFound, details: [])); falling back to secondary model "gemini-2.5-flash-lite".
2026-04-29 17:51:09.249206+0000 FirebaseAITestApp-SPM[12012:82381] [IPC] Passing along Model Catalog error: Error Domain=com.apple.UnifiedAssetFramework Code=5000 "There are no underlying assets (neither atomic instance nor asset roots) for consistency token for asset set com.apple.MobileAsset.UAF.FM.Overrides" UserInfo={NSLocalizedFailureReason=There are no underlying assets (neither atomic instance nor asset roots) for consistency token for asset set com.apple.MobileAsset.UAF.FM.Overrides} in response to ExecuteRequest
2026-04-29 17:51:10.066276+0000 FirebaseAITestApp-SPM[12012:90619] [IPC] Passing along Model Catalog error: Error Domain=com.apple.UnifiedAssetFramework Code=5000 "There are no underlying assets (neither atomic instance nor asset roots) for consistency token for asset set com.apple.MobileAsset.UAF.FM.Overrides" UserInfo={NSLocalizedFailureReason=There are no underlying assets (neither atomic instance nor asset roots) for consistency token for asset set com.apple.MobileAsset.UAF.FM.Overrides} in response to ExecuteRequest
​✔ Test respondText_fallbackOnFoundationModelsError(_:) with 1 test case passed after 2.998 seconds.
◇ Test respondGenerable_fallbackOnGeminiModelError(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondGenerable_fallbackOnGeminiModelError(_:) started.
​✔ Test respondGenerable_fallbackOnGeminiModelError(_:) with 1 test case passed after 1.285 seconds.
◇ Test streamResponseText_fallbackOnGeminiModelError(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to streamResponseText_fallbackOnGeminiModelError(_:) started.
​✔ Test streamResponseText_fallbackOnGeminiModelError(_:) with 1 test case passed after 0.898 seconds.
◇ Test streamResponseGenerable_fallbackOnGeminiModelError(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to streamResponseGenerable_fallbackOnGeminiModelError(_:) started.
2026-04-29 17:51:09.290401+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004009] Primary model "apple-foundation-models-system-language-model" failed with error: Error Domain=FoundationModels.LanguageModelSession.GenerationError Code=-1 "(null)" UserInfo={NSMultipleUnderlyingErrorsKey=(
    "Error Domain=FoundationModels.LanguageModelSession.GenerationError Code=-1 \"(null)\" UserInfo={NSMultipleUnderlyingErrorsKey=(\n    \"Error Domain=ModelManagerServices.ModelManagerError Code=1026 \\\"(null)\\\" UserInfo={NSMultipleUnderlyingErrorsKey=(\\n)}\"\n)}"
)}; falling back to secondary model "gemini-2.5-flash-lite".
2026-04-29 17:51:13.590653+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002001] The server responded with an error: <NSHTTPURLResponse: 0x1071f3100> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name-1:generateContent } { Status Code: 404, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Encoding" =     (
        gzip
    );
    "Content-Length" =     (
        284
    );
    "Content-Type" =     (
        "application/json; charset=UTF-8"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:51:10 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
2026-04-29 17:51:13.653090+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002002] Response payload: {
  "error": {
    "code": 404,
    "message": "Publisher Model `projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name-1` was not found or your project does not have access to it. Please ensure you are using a valid model version. For more information, see: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versions",
    "status": "NOT_FOUND"
  }
}
2026-04-29 17:51:13.711341+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004009] Primary model "invalid-model-name-1" failed with error: internalError(underlying: FirebaseAILogic.BackendError(httpResponseCode: 404, message: "Publisher Model `projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name-1` was not found or your project does not have access to it. Please ensure you are using a valid model version. For more information, see: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versions", status: FirebaseAILogic.RPCStatus.notFound, details: [])); falling back to secondary model "gemini-2.5-flash-lite".
2026-04-29 17:51:13.753553+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002003] The server responded with an error: <NSHTTPURLResponse: 0x1071f3140> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name:streamGenerateContent?alt=sse } { Status Code: 404, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Length" =     (
        404
    );
    "Content-Type" =     (
        "text/event-stream"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:51:11 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
​✔ Test streamResponseGenerable_fallbackOnGeminiModelError(_:) with 1 test case passed after 1.558 seconds.
◇ Test streamResponseText_fallbackOnFoundationModelsError(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to streamResponseText_fallbackOnFoundationModelsError(_:) started.
2026-04-29 17:51:13.847653+0000 FirebaseAITestApp-SPM[12012:50297] [IPC] Passing along Model Catalog error: Error Domain=com.apple.UnifiedAssetFramework Code=5000 "There are no underlying assets (neither atomic instance nor asset roots) for consistency token for asset set com.apple.MobileAsset.UAF.FM.Overrides" UserInfo={NSLocalizedFailureReason=There are no underlying assets (neither atomic instance nor asset roots) for consistency token for asset set com.apple.MobileAsset.UAF.FM.Overrides} in response to ExecuteRequest
2026-04-29 17:51:13.807922+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002004] Response payload: {
  "error": {
    "code": 404,
    "message": "Publisher Model `projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name` was not found or your project does not have access to it. Please ensure you are using a valid model version. For more information, see: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versions",
    "status": "NOT_FOUND"
  }
}
2026-04-29 17:51:13.859512+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004010] Primary model "invalid-model-name" failed with error: internalError(underlying: FirebaseAILogic.BackendError(httpResponseCode: 404, message: "Publisher Model `projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name` was not found or your project does not have access to it. Please ensure you are using a valid model version. For more information, see: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versions", status: FirebaseAILogic.RPCStatus.notFound, details: [])); falling back to secondary model "gemini-2.5-flash-lite".
2026-04-29 17:51:13.961714+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002003] The server responded with an error: <NSHTTPURLResponse: 0x1071f3f40> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name:streamGenerateContent?alt=sse } { Status Code: 404, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Length" =     (
        404
    );
    "Content-Type" =     (
        "text/event-stream"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:51:12 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
2026-04-29 17:51:13.977282+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002004] Response payload: {
  "error": {
    "code": 404,
    "message": "Publisher Model `projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name` was not found or your project does not have access to it. Please ensure you are using a valid model version. For more information, see: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versions",
    "status": "NOT_FOUND"
  }
}
2026-04-29 17:51:13.981466+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004010] Primary model "invalid-model-name" failed with error: internalError(underlying: FirebaseAILogic.BackendError(httpResponseCode: 404, message: "Publisher Model `projects/ios-opensource-samples/locations/global/publishers/google/models/invalid-model-name` was not found or your project does not have access to it. Please ensure you are using a valid model version. For more information, see: https://cloud.google.com/vertex-ai/generative-ai/docs/learn/model-versions", status: FirebaseAILogic.RPCStatus.notFound, details: [])); falling back to secondary model "gemini-2.5-flash-lite".
2026-04-29 17:51:13.982170+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004010] Primary model "apple-foundation-models-system-language-model" failed with error: Error Domain=FoundationModels.LanguageModelSession.GenerationError Code=-1 "(null)" UserInfo={NSMultipleUnderlyingErrorsKey=(
    "Error Domain=FoundationModels.LanguageModelSession.GenerationError Code=-1 \"(null)\" UserInfo={NSMultipleUnderlyingErrorsKey=(\n    \"Error Domain=ModelManagerServices.ModelManagerError Code=1026 \\\"(null)\\\" UserInfo={NSMultipleUnderlyingErrorsKey=(\\n)}\"\n)}"
)}; falling back to secondary model "gemini-2.5-flash-lite".
2026-04-29 17:51:14.440036+0000 FirebaseAITestApp-SPM[12012:82381] [IPC] Passing along Model Catalog error: Error Domain=com.apple.UnifiedAssetFramework Code=5000 "There are no underlying assets (neither atomic instance nor asset roots) for consistency token for asset set com.apple.MobileAsset.UAF.FM.Overrides" UserInfo={NSLocalizedFailureReason=There are no underlying assets (neither atomic instance nor asset roots) for consistency token for asset set com.apple.MobileAsset.UAF.FM.Overrides} in response to ExecuteRequest
​✔ Test streamResponseText_fallbackOnFoundationModelsError(_:) with 1 test case passed after 0.629 seconds.
✔ Suite GenerativeModelSessionHybridTests passed after 10.194 seconds.
◇ Suite GenerativeModelSessionTests started.
◇ Test respondText(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondText(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to respondText(_:) started.
2026-04-29 17:51:25.006419+0000 FirebaseAITestApp-SPM[12012:90317] [connection] nw_read_request_report [C6] Receive failed with error "Socket is not connected"
2026-04-29 17:51:25.006532+0000 FirebaseAITestApp-SPM[12012:90317] [connection] nw_read_request_report [C6] Receive failed with error "Socket is not connected"
2026-04-29 17:51:25.006700+0000 FirebaseAITestApp-SPM[12012:90317] [connection] nw_read_request_report [C6] Receive failed with error "Socket is not connected"
2026-04-29 17:51:25.007651+0000 FirebaseAITestApp-SPM[12012:90317] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C6] Connection has no local endpoint
​✔ Test respondText(_:) with 2 test cases passed after 10.955 seconds.
◇ Test respondGeneratedContent(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondGeneratedContent(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to respondGeneratedContent(_:) started.
​✔ Test respondGeneratedContent(_:) with 2 test cases passed after 8.780 seconds.
◇ Test respondGenerable(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondGenerable(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to respondGenerable(_:) started.
​✔ Test respondGenerable(_:) with 2 test cases passed after 7.468 seconds.
◇ Test respondGenerableRecipe(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondGenerableRecipe(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to respondGenerableRecipe(_:) started.
​✔ Test respondGenerableRecipe(_:) with 2 test cases passed after 12.312 seconds.
◇ Test respondGenerableRecipeList(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondGenerableRecipeList(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to respondGenerableRecipeList(_:) started.
​✔ Test respondGenerableRecipeList(_:) with 2 test cases passed after 11.329 seconds.
◇ Test respondTextWithAutomaticFunctionCalling(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondTextWithAutomaticFunctionCalling(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to respondTextWithAutomaticFunctionCalling(_:) started.
​✔ Test respondTextWithAutomaticFunctionCalling(_:) with 2 test cases passed after 5.524 seconds.
◇ Test respondGenerableWithAutomaticFunctionCalling(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondGenerableWithAutomaticFunctionCalling(_:) started.
✘ Test respondGenerableWithAutomaticFunctionCalling(_:) recorded an issue with 1 argument config → Vertex AI (v1beta) - (global) at GenerativeModelSessionTests.swift:308:6: Caught error: internalError(underlying: FirebaseAILogic.BackendError(httpResponseCode: 429, message: "Resource has been exhausted (e.g. check quota).", status: FirebaseAILogic.RPCStatus.resourceExhausted, details: []))
​◇ Test case passing 1 argument config → Google AI (v1beta) to respondGenerableWithAutomaticFunctionCalling(_:) started.
2026-04-29 17:52:12.513296+0000 FirebaseAITestApp-SPM[12012:102250] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002001] The server responded with an error: <NSHTTPURLResponse: 0x1071f18c0> { URL: https://firebasevertexai.googleapis.com/v1beta/projects/ios-opensource-samples/locations/global/publishers/google/models/gemini-3.1-flash-lite-preview:generateContent } { Status Code: 429, Headers {
    "Alt-Svc" =     (
        "h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000"
    );
    "Content-Encoding" =     (
        gzip
    );
    "Content-Length" =     (
        139
    );
    "Content-Type" =     (
        "application/json; charset=UTF-8"
    );
    Date =     (
        "Wed, 29 Apr 2026 17:52:12 GMT"
    );
    Server =     (
        ESF
    );
    Vary =     (
        Origin,
        "X-Origin",
        Referer
    );
    "x-content-type-options" =     (
        nosniff
    );
    "x-frame-options" =     (
        SAMEORIGIN
    );
    "x-xss-protection" =     (
        0
    );
} }
2026-04-29 17:52:12.513608+0000 FirebaseAITestApp-SPM[12012:102250] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX002002] Response payload: {
  "error": {
    "code": 429,
    "message": "Resource has been exhausted (e.g. check quota).",
    "status": "RESOURCE_EXHAUSTED"
  }
}
​✘ Test respondGenerableWithAutomaticFunctionCalling(_:) with 2 test cases failed after 4.616 seconds with 1 issue.
◇ Test respondTextWithURLContext(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to respondTextWithURLContext(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to respondTextWithURLContext(_:) started.
​✔ Test respondTextWithURLContext(_:) with 2 test cases passed after 10.343 seconds.
◇ Test streamResponseText(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to streamResponseText(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to streamResponseText(_:) started.
​✔ Test streamResponseText(_:) with 2 test cases passed after 9.950 seconds.
◇ Test streamResponseGeneratedContent(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to streamResponseGeneratedContent(_:) started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to streamResponseGeneratedContent(_:) started.
​✔ Test streamResponseGeneratedContent(_:) with 2 test cases passed after 1.933 seconds.
◇ Test streamResponseGenerable(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to streamResponseGenerable(_:) started.
2026-04-29 17:52:39.771024+0000 FirebaseAITestApp-SPM[12012:90618] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from any candidates.
2026-04-29 17:52:39.783023+0000 FirebaseAITestApp-SPM[12012:90317] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from any candidates.
​◇ Test case passing 1 argument config → Google AI (v1beta) to streamResponseGenerable(_:) started.
​✔ Test streamResponseGenerable(_:) with 2 test cases passed after 4.025 seconds.
◇ Test streamResponseTextWithAutomaticFunctionCalling(_:) started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to streamResponseTextWithAutomaticFunctionCalling(_:) started.
2026-04-29 17:52:41.701531+0000 FirebaseAITestApp-SPM[12012:105731] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from any candidates.
2026-04-29 17:52:41.706667+0000 FirebaseAITestApp-SPM[12012:105731] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX004001] Could not get a text part from any candidates.
​◇ Test case passing 1 argument config → Google AI (v1beta) to streamResponseTextWithAutomaticFunctionCalling(_:) started.
​✔ Test streamResponseTextWithAutomaticFunctionCalling(_:) with 2 test cases passed after 4.726 seconds.
✘ Suite GenerativeModelSessionTests failed after 91.971 seconds with 1 issue.
◇ Suite ImagenIntegrationTests started.
◇ Test generateImage_inlineImage() started.
✔ Test generateImage_inlineImage() passed after 9.134 seconds.
◇ Test generateImage_allImagesFilteredOut() started.
✔ Test generateImage_allImagesFilteredOut() passed after 7.052 seconds.
✔ Suite ImagenIntegrationTests passed after 16.187 seconds.
◇ Suite ImplicitCacheTests started.
◇ Test implicitCaching(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-2.5-flash" to implicitCaching(_:modelName:) started.
2026-04-29 17:53:02.617780+0000 FirebaseAITestApp-SPM[12012:106422] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX003000] JSON response: {
  "predictions": [
    {
      "raiFilteredReason": "Your request resulted in one or more images that contained people. They are filtered out because you selected the 'Don't allow' option for Person Generation. You can send this request again using the 'Allow (All ages)' or 'Allow (Adults only)' options. See the safety settings documentation for more details. If you think this was an error, send feedback. Support codes: 39322892, 63236870"
    },
    {
      "contentType": "Positive Prompt",
      "safetyAttributes": {
        "scores": [
          0.1,
          0.1,
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          0.1
        ],
        "categories": [
          "Death, Harm & Tragedy",
          "Firearms & Weapons",
          "Hate",
          "Health",
          "Illicit Drugs",
          "Politics",
          "Porn",
          "Religion & Belief",
          "Toxic",
          "Violence",
          "Vulgarity",
          "War & Conflict"
        ]
      }
    }
  ]
}
2026-04-29 17:53:02.621455+0000 FirebaseAITestApp-SPM[12012:106422] [[FirebaseAI]] 12.13.0 - [FirebaseAI][I-VTX003001] Error decoding server JSON: ImagenImagesBlockedError(message: "Your request resulted in one or more images that contained people. They are filtered out because you selected the \'Don\'t allow\' option for Person Generation. You can send this request again using the \'Allow (All ages)\' or \'Allow (Adults only)\' options. See the safety settings documentation for more details. If you think this was an error, send feedback. Support codes: 39322892, 63236870")
Implicit cache miss. This test might be flaky if the backend doesn't cache immediately.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash" to implicitCaching(_:modelName:) started.
Implicit cache hit! cachedContentTokenCount: 6123
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-pro" to implicitCaching(_:modelName:) started.
Implicit cache hit! cachedContentTokenCount: 4082
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-3.1-flash-lite-preview" to implicitCaching(_:modelName:) started.
Implicit cache hit! cachedContentTokenCount: 4077
​✔ Test implicitCaching(_:modelName:) with 4 test cases passed after 17.540 seconds.
✔ Suite ImplicitCacheTests passed after 17.540 seconds.
◇ Suite LiveSessionTests started.
◇ Test sendAudioRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" to sendAudioRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1) - FAC Limited-Use, modelName → "gemini-live-2.5-flash-native-audio" to sendAudioRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
2026-04-29 17:53:22.860841+0000 FirebaseAITestApp-SPM[12012:106422] [connection] nw_connection_copy_protocol_metadata_internal_block_invoke [C12] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection
2026-04-29 17:53:22.860940+0000 FirebaseAITestApp-SPM[12012:106422] [connection] nw_connection_copy_protocol_metadata_internal_block_invoke [C12] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection
2026-04-29 17:53:22.861021+0000 FirebaseAITestApp-SPM[12012:106422] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C12] Client called nw_connection_copy_connected_local_endpoint on unconnected nw_connection
2026-04-29 17:53:22.861077+0000 FirebaseAITestApp-SPM[12012:106422] [connection] nw_connection_copy_connected_remote_endpoint_block_invoke [C12] Client called nw_connection_copy_connected_remote_endpoint on unconnected nw_connection
2026-04-29 17:53:22.861757+0000 FirebaseAITestApp-SPM[12012:106422] [] nw_protocol_instance_set_output_handler Not calling remove_input_handler on 0x111f8b600:socket
2026-04-29 17:53:22.862378+0000 FirebaseAITestApp-SPM[12012:106422] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C10] Connection has no local endpoint
2026-04-29 17:53:22.862556+0000 FirebaseAITestApp-SPM[12012:106422] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C10] Connection has no local endpoint
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to sendAudioRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to sendAudioRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to sendAudioRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
​✔ Test sendAudioRealtime_receiveAudioOutputTranscripts(_:modelName:) with 5 test cases passed after 17.273 seconds.
◇ Test sendVideoRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" to sendVideoRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
2026-04-29 17:53:38.488546+0000 FirebaseAITestApp-SPM[12012:102250] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:53:38.543881+0000 FirebaseAITestApp-SPM[12012:102250] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:53:38.555923+0000 FirebaseAITestApp-SPM[12012:102250] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:53:38.574590+0000 FirebaseAITestApp-SPM[12012:102250] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:53:38.588117+0000 FirebaseAITestApp-SPM[12012:102250] [] (Fig) signalled err=-12900 at <>:1242
✘ Test sendVideoRealtime_receiveAudioOutputTranscripts(_:modelName:) recorded an issue with 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" at LiveSessionTests.swift:148:4: Time limit was exceeded: 60.000 seconds
✘ Test sendVideoRealtime_receiveAudioOutputTranscripts(_:modelName:) recorded an issue with 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" at LiveSessionTests.swift:198:5: Expectation failed: ["kitten", "cat", "kitty"].contains(modelResponse → "")
↳ // model response varies
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1) - FAC Limited-Use, modelName → "gemini-live-2.5-flash-native-audio" to sendVideoRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
2026-04-29 17:54:38.491278+0000 FirebaseAITestApp-SPM[12012:90317] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:38.515708+0000 FirebaseAITestApp-SPM[12012:90317] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:38.533539+0000 FirebaseAITestApp-SPM[12012:90317] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:38.550309+0000 FirebaseAITestApp-SPM[12012:90317] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:38.567420+0000 FirebaseAITestApp-SPM[12012:90317] [] (Fig) signalled err=-12900 at <>:1242
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to sendVideoRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
2026-04-29 17:54:42.743232+0000 FirebaseAITestApp-SPM[12012:113426] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:42.764115+0000 FirebaseAITestApp-SPM[12012:113426] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:42.778854+0000 FirebaseAITestApp-SPM[12012:113426] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:42.794526+0000 FirebaseAITestApp-SPM[12012:113426] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:42.808689+0000 FirebaseAITestApp-SPM[12012:113426] [] (Fig) signalled err=-12900 at <>:1242
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to sendVideoRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
2026-04-29 17:54:48.503763+0000 FirebaseAITestApp-SPM[12012:105731] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:48.521659+0000 FirebaseAITestApp-SPM[12012:105731] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:48.535538+0000 FirebaseAITestApp-SPM[12012:105731] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:48.549391+0000 FirebaseAITestApp-SPM[12012:105731] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:48.563033+0000 FirebaseAITestApp-SPM[12012:105731] [] (Fig) signalled err=-12900 at <>:1242
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to sendVideoRealtime_receiveAudioOutputTranscripts(_:modelName:) started.
2026-04-29 17:54:53.414693+0000 FirebaseAITestApp-SPM[12012:90317] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:53.428323+0000 FirebaseAITestApp-SPM[12012:90317] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:53.440526+0000 FirebaseAITestApp-SPM[12012:90317] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:53.452150+0000 FirebaseAITestApp-SPM[12012:90317] [] (Fig) signalled err=-12900 at <>:1242
2026-04-29 17:54:53.464170+0000 FirebaseAITestApp-SPM[12012:90317] [] (Fig) signalled err=-12900 at <>:1242
​✘ Test sendVideoRealtime_receiveAudioOutputTranscripts(_:modelName:) with 5 test cases failed after 80.369 seconds with 2 issues.
◇ Test realtime_functionCalling(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" to realtime_functionCalling(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1) - FAC Limited-Use, modelName → "gemini-live-2.5-flash-native-audio" to realtime_functionCalling(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_functionCalling(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_functionCalling(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_functionCalling(_:modelName:) started.


*** If you believe this error represents a bug, please attach the result bundle at /Users/runner/Library/Developer/Xcode/DerivedData/FirebaseAITestApp-bwahwmquzihedieofiheylkbrdnf/Logs/Test/Test-FirebaseAITestApp-SPM-2026.04.29_17-41-21-+0000.xcresult

2026-04-29 17:55:16.580246+0000 FirebaseAITestApp-SPM[50639:129008] [[GoogleUtilities/AppDelegateSwizzler]] 12.13.0 - [GoogleUtilities/AppDelegateSwizzler][I-SWZ001014] App Delegate does not conform to UIApplicationDelegate protocol.
2026-04-29 17:55:16.604256+0000 FirebaseAITestApp-SPM[50639:129008] [[FirebaseAppCheck]] 12.13.0 - [FirebaseAppCheck][I-FAA002002] Cannot instantiate `FIRAppCheck` for app: app-check-not-configured without an app check provider. Please make sure the provider factory returns a valid app check provider.
2026-04-29 17:55:16.604481+0000 FirebaseAITestApp-SPM[50639:129008] [[FirebaseAppCheck]] 12.13.0 - [FirebaseAppCheck][I-FAA002002] Cannot instantiate `FIRAppCheck` for app: app-check-not-configured without an app check provider. Please make sure the provider factory returns a valid app check provider.

Restarting after unexpected exit, crash, or test timeout; summary will include totals from previous launches.

Test Suite 'Selected tests' started at 2026-04-29 17:55:21.254.
Test Suite 'IntegrationTests-SPM.xctest' started at 2026-04-29 17:55:21.256.
Test Suite 'IntegrationTests-SPM.xctest' passed at 2026-04-29 17:55:21.256.
	 Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.000) seconds
Test Suite 'Selected tests' passed at 2026-04-29 17:55:21.256.
	 Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.003) seconds
◇ Test run started.
↳ Testing Library Version: 1501
↳ Target Platform: arm64-apple-ios13.0-simulator
◇ Iteration 1 started.
◇ Suite LiveSessionTests started.
◇ Test realtime_functionCalling(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" to realtime_functionCalling(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1) - FAC Limited-Use, modelName → "gemini-live-2.5-flash-native-audio" to realtime_functionCalling(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_functionCalling(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_functionCalling(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_functionCalling(_:modelName:) started.
​✔ Test realtime_functionCalling(_:modelName:) with 5 test cases passed after 16.245 seconds.
◇ Test realtime_manual_sessionResumption(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" to realtime_manual_sessionResumption(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1) - FAC Limited-Use, modelName → "gemini-live-2.5-flash-native-audio" to realtime_manual_sessionResumption(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_manual_sessionResumption(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_manual_sessionResumption(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_manual_sessionResumption(_:modelName:) started.
​✔ Test realtime_manual_sessionResumption(_:modelName:) with 5 test cases passed after 24.940 seconds.
◇ Test realtime_sessionResumption_disabled(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" to realtime_sessionResumption_disabled(_:modelName:) started.
✘ Test realtime_sessionResumption_disabled(_:modelName:) recorded an issue with 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" at LiveSessionTests.swift:314:4: Time limit was exceeded: 60.000 seconds
✘ Test realtime_sessionResumption_disabled(_:modelName:) recorded an issue with 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" at LiveSessionTests.swift:357:5: Expectation failed: (modelResponse → "") == "michael"
↳ // the default name per the system instructions
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1) - FAC Limited-Use, modelName → "gemini-live-2.5-flash-native-audio" to realtime_sessionResumption_disabled(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_sessionResumption_disabled(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_sessionResumption_disabled(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_sessionResumption_disabled(_:modelName:) started.
​✘ Test realtime_sessionResumption_disabled(_:modelName:) with 5 test cases failed after 73.953 seconds with 2 issues.
◇ Test realtime_resumeSession(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" to realtime_resumeSession(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1) - FAC Limited-Use, modelName → "gemini-live-2.5-flash-native-audio" to realtime_resumeSession(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_resumeSession(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_resumeSession(_:modelName:) started.


*** If you believe this error represents a bug, please attach the result bundle at /Users/runner/Library/Developer/Xcode/DerivedData/FirebaseAITestApp-bwahwmquzihedieofiheylkbrdnf/Logs/Test/Test-FirebaseAITestApp-SPM-2026.04.29_17-41-21-+0000.xcresult

2026-04-29 17:57:37.408114+0000 FirebaseAITestApp-SPM[59056:147948] [[GoogleUtilities/AppDelegateSwizzler]] 12.13.0 - [GoogleUtilities/AppDelegateSwizzler][I-SWZ001014] App Delegate does not conform to UIApplicationDelegate protocol.
2026-04-29 17:57:37.412935+0000 FirebaseAITestApp-SPM[59056:147948] [[FirebaseAppCheck]] 12.13.0 - [FirebaseAppCheck][I-FAA002002] Cannot instantiate `FIRAppCheck` for app: app-check-not-configured without an app check provider. Please make sure the provider factory returns a valid app check provider.
2026-04-29 17:57:37.413129+0000 FirebaseAITestApp-SPM[59056:147948] [[FirebaseAppCheck]] 12.13.0 - [FirebaseAppCheck][I-FAA002002] Cannot instantiate `FIRAppCheck` for app: app-check-not-configured without an app check provider. Please make sure the provider factory returns a valid app check provider.

Restarting after unexpected exit, crash, or test timeout; summary will include totals from previous launches.

Test Suite 'Selected tests' started at 2026-04-29 17:57:39.390.
Test Suite 'IntegrationTests-SPM.xctest' started at 2026-04-29 17:57:39.390.
Test Suite 'IntegrationTests-SPM.xctest' passed at 2026-04-29 17:57:39.390.
	 Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.000) seconds
Test Suite 'Selected tests' passed at 2026-04-29 17:57:39.390.
	 Executed 0 tests, with 0 failures (0 unexpected) in 0.000 (0.001) seconds
◇ Test run started.
↳ Testing Library Version: 1501
↳ Target Platform: arm64-apple-ios13.0-simulator
◇ Iteration 1 started.
◇ Suite LiveSessionTests started.
◇ Test realtime_resumeSession(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" to realtime_resumeSession(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1) - FAC Limited-Use, modelName → "gemini-live-2.5-flash-native-audio" to realtime_resumeSession(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_resumeSession(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_resumeSession(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_resumeSession(_:modelName:) started.
​✔ Test realtime_resumeSession(_:modelName:) with 5 test cases passed after 26.101 seconds.
◇ Test realtime_functionCalling_cancellation(_:modelName:) started.
◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_functionCalling_cancellation(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_functionCalling_cancellation(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_functionCalling_cancellation(_:modelName:) started.
​✔ Test realtime_functionCalling_cancellation(_:modelName:) with 3 test cases passed after 6.351 seconds.
◇ Test realtime_interruption(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" to realtime_interruption(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_interruption(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to realtime_interruption(_:modelName:) started.
​✔ Test realtime_interruption(_:modelName:) with 3 test cases passed after 7.836 seconds.
◇ Test incremental_works(_:modelName:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), modelName → "gemini-live-2.5-flash-native-audio" to incremental_works(_:modelName:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1) - FAC Limited-Use, modelName → "gemini-live-2.5-flash-native-audio" to incremental_works(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to incremental_works(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to incremental_works(_:modelName:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - Free Tier, modelName → "gemini-2.5-flash-native-audio-preview-12-2025" to incremental_works(_:modelName:) started.
​✔ Test incremental_works(_:modelName:) with 5 test cases passed after 12.353 seconds.
✔ Suite LiveSessionTests passed after 52.645 seconds.
◇ Suite MapsGroundingIntegrationTests started.
◇ Test "generateContent with Google Maps returns grounding metadata" started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to "generateContent with Google Maps returns grounding metadata" started.
2026-04-29 17:58:32.205999+0000 FirebaseAITestApp-SPM[59056:147942] [connection] nw_connection_copy_protocol_metadata_internal_block_invoke [C25] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection
2026-04-29 17:58:32.206121+0000 FirebaseAITestApp-SPM[59056:147942] [connection] nw_connection_copy_protocol_metadata_internal_block_invoke [C25] Client called nw_connection_copy_protocol_metadata_internal on unconnected nw_connection
2026-04-29 17:58:32.206196+0000 FirebaseAITestApp-SPM[59056:147942] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C25] Client called nw_connection_copy_connected_local_endpoint on unconnected nw_connection
2026-04-29 17:58:32.206244+0000 FirebaseAITestApp-SPM[59056:147942] [connection] nw_connection_copy_connected_remote_endpoint_block_invoke [C25] Client called nw_connection_copy_connected_remote_endpoint on unconnected nw_connection
2026-04-29 17:58:32.208372+0000 FirebaseAITestApp-SPM[59056:147942] [] nw_protocol_instance_set_output_handler Not calling remove_input_handler on 0x1035faa00:socket
2026-04-29 17:58:32.210666+0000 FirebaseAITestApp-SPM[59056:147942] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C23] Connection has no local endpoint
2026-04-29 17:58:32.210909+0000 FirebaseAITestApp-SPM[59056:147942] [connection] nw_connection_copy_connected_local_endpoint_block_invoke [C23] Connection has no local endpoint
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to "generateContent with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to "generateContent with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to "generateContent with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to "generateContent with Google Maps returns grounding metadata" started.
​✔ Test "generateContent with Google Maps returns grounding metadata" with 5 test cases passed after 36.788 seconds.
◇ Test "respondTo with Google Maps returns grounding metadata" started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to "respondTo with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to "respondTo with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to "respondTo with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to "respondTo with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to "respondTo with Google Maps returns grounding metadata" started.
​✔ Test "respondTo with Google Maps returns grounding metadata" with 5 test cases passed after 36.133 seconds.
◇ Test "streamResponse with Google Maps returns grounding metadata" started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to "streamResponse with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to "streamResponse with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to "streamResponse with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to "streamResponse with Google Maps returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to "streamResponse with Google Maps returns grounding metadata" started.
​✔ Test "streamResponse with Google Maps returns grounding metadata" with 5 test cases passed after 31.364 seconds.
◇ Test "generateContent with Google Maps and RetrievalConfig returns grounding metadata" started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to "generateContent with Google Maps and RetrievalConfig returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to "generateContent with Google Maps and RetrievalConfig returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to "generateContent with Google Maps and RetrievalConfig returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to "generateContent with Google Maps and RetrievalConfig returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to "generateContent with Google Maps and RetrievalConfig returns grounding metadata" started.
​✔ Test "generateContent with Google Maps and RetrievalConfig returns grounding metadata" with 5 test cases passed after 36.653 seconds.
◇ Test "generateContent with Google Maps and languageCode returns grounding metadata" started.
◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to "generateContent with Google Maps and languageCode returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to "generateContent with Google Maps and languageCode returns grounding metadata" started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) - FAC Limited-Use to "generateContent with Google Maps and languageCode returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) to "generateContent with Google Maps and languageCode returns grounding metadata" started.
​◇ Test case passing 1 argument config → Google AI (v1beta) - FAC Limited-Use to "generateContent with Google Maps and languageCode returns grounding metadata" started.
​✔ Test "generateContent with Google Maps and languageCode returns grounding metadata" with 5 test cases passed after 40.954 seconds.
✔ Suite MapsGroundingIntegrationTests passed after 181.896 seconds.
◇ Suite SchemaTests started.
◇ Test generateContentItemsSchema(_:_:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), schema → OpenAPI Schema to generateContentItemsSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), schema → JSON Schema to generateContentItemsSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), schema → OpenAPI Schema to generateContentItemsSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), schema → JSON Schema to generateContentItemsSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global) - FAC Limited-Use, schema → OpenAPI Schema to generateContentItemsSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global) - FAC Limited-Use, schema → JSON Schema to generateContentItemsSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), schema → OpenAPI Schema to generateContentItemsSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), schema → JSON Schema to generateContentItemsSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, schema → OpenAPI Schema to generateContentItemsSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, schema → JSON Schema to generateContentItemsSchema(_:_:) started.
​✔ Test generateContentItemsSchema(_:_:) with 10 test cases passed after 10.266 seconds.
◇ Test generateContentSchemaNumberRange(_:_:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), schema → OpenAPI Schema to generateContentSchemaNumberRange(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), schema → JSON Schema to generateContentSchemaNumberRange(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), schema → OpenAPI Schema to generateContentSchemaNumberRange(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), schema → JSON Schema to generateContentSchemaNumberRange(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global) - FAC Limited-Use, schema → OpenAPI Schema to generateContentSchemaNumberRange(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global) - FAC Limited-Use, schema → JSON Schema to generateContentSchemaNumberRange(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), schema → OpenAPI Schema to generateContentSchemaNumberRange(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), schema → JSON Schema to generateContentSchemaNumberRange(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, schema → OpenAPI Schema to generateContentSchemaNumberRange(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, schema → JSON Schema to generateContentSchemaNumberRange(_:_:) started.
​✔ Test generateContentSchemaNumberRange(_:_:) with 10 test cases passed after 24.892 seconds.
◇ Test generateContentSchemaNumberRangeMultiType(_:_:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), schema → OpenAPI Schema to generateContentSchemaNumberRangeMultiType(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), schema → JSON Schema to generateContentSchemaNumberRangeMultiType(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), schema → OpenAPI Schema to generateContentSchemaNumberRangeMultiType(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), schema → JSON Schema to generateContentSchemaNumberRangeMultiType(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global) - FAC Limited-Use, schema → OpenAPI Schema to generateContentSchemaNumberRangeMultiType(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global) - FAC Limited-Use, schema → JSON Schema to generateContentSchemaNumberRangeMultiType(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), schema → OpenAPI Schema to generateContentSchemaNumberRangeMultiType(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), schema → JSON Schema to generateContentSchemaNumberRangeMultiType(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, schema → OpenAPI Schema to generateContentSchemaNumberRangeMultiType(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, schema → JSON Schema to generateContentSchemaNumberRangeMultiType(_:_:) started.
​✔ Test generateContentSchemaNumberRangeMultiType(_:_:) with 10 test cases passed after 43.752 seconds.
◇ Test generateContentAnyOfSchema(_:_:) started.
◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), schema → OpenAPI Schema to generateContentAnyOfSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (us-central1), schema → JSON Schema to generateContentAnyOfSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), schema → OpenAPI Schema to generateContentAnyOfSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global), schema → JSON Schema to generateContentAnyOfSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global) - FAC Limited-Use, schema → OpenAPI Schema to generateContentAnyOfSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Vertex AI (v1beta) - (global) - FAC Limited-Use, schema → JSON Schema to generateContentAnyOfSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), schema → OpenAPI Schema to generateContentAnyOfSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta), schema → JSON Schema to generateContentAnyOfSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, schema → OpenAPI Schema to generateContentAnyOfSchema(_:_:) started.
​◇ Test case passing 2 arguments config → Google AI (v1beta) - FAC Limited-Use, schema → JSON Schema to generateContentAnyOfSchema(_:_:) started.
​✔ Test generateContentAnyOfSchema(_:_:) with 10 test cases passed after 36.646 seconds.
✔ Suite SchemaTests passed after 115.558 seconds.
◇ Suite ServerPromptTemplateIntegrationTests started.
◇ Test generateContentWithText(_:) started.
◇ Test case passing 1 argument config → Google AI (v1beta) to generateContentWithText(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to generateContentWithText(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to generateContentWithText(_:) started.
​✔ Test generateContentWithText(_:) with 3 test cases passed after 14.906 seconds.
◇ Test generateContentStream(_:) started.
◇ Test case passing 1 argument config → Google AI (v1beta) to generateContentStream(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to generateContentStream(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to generateContentStream(_:) started.
​✔ Test generateContentStream(_:) with 3 test cases passed after 9.699 seconds.
◇ Test generateContentWithTemplateMapsGrounding(_:) started.
◇ Test case passing 1 argument config → Google AI (v1beta) to generateContentWithTemplateMapsGrounding(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to generateContentWithTemplateMapsGrounding(_:) started.
​✔ Test generateContentWithTemplateMapsGrounding(_:) with 2 test cases passed after 9.661 seconds.
◇ Test generateImages(_:) started.
◇ Test case passing 1 argument config → Google AI (v1beta) to generateImages(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to generateImages(_:) started.
​✔ Test generateImages(_:) with 2 test cases passed after 23.209 seconds.
◇ Test generateContentWithMedia(_:) started.
◇ Test case passing 1 argument config → Google AI (v1beta) to generateContentWithMedia(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to generateContentWithMedia(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to generateContentWithMedia(_:) started.
​✔ Test generateContentWithMedia(_:) with 3 test cases passed after 5.369 seconds.
◇ Test generateContentStreamWithMedia(_:) started.
◇ Test case passing 1 argument config → Google AI (v1beta) to generateContentStreamWithMedia(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to generateContentStreamWithMedia(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to generateContentStreamWithMedia(_:) started.
​✔ Test generateContentStreamWithMedia(_:) with 3 test cases passed after 4.620 seconds.
◇ Test chat(_:) started.
◇ Test case passing 1 argument config → Google AI (v1beta) to chat(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to chat(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to chat(_:) started.
​✔ Test chat(_:) with 3 test cases passed after 3.541 seconds.
◇ Test chatStream(_:) started.
◇ Test case passing 1 argument config → Google AI (v1beta) to chatStream(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (us-central1) to chatStream(_:) started.
​◇ Test case passing 1 argument config → Vertex AI (v1beta) - (global) to chatStream(_:) started.
​✔ Test chatStream(_:) with 3 test cases passed after 2.193 seconds.
✔ Suite ServerPromptTemplateIntegrationTests passed after 73.203 seconds.
◇ Iteration 1 ended after 423.304 seconds.
✔ Test run with 21 tests in 4 suites passed after 423.304 seconds.
2026-04-29 18:05:13.445 xcodebuild[10872:35316] [MT] IDETestOperationsObserverDebug: 1428.281 elapsed -- Testing started completed.
2026-04-29 18:05:13.446 xcodebuild[10872:35316] [MT] IDETestOperationsObserverDebug: 0.000 sec, +0.000 sec -- start
2026-04-29 18:05:13.446 xcodebuild[10872:35316] [MT] IDETestOperationsObserverDebug: 1428.281 sec, +1428.281 sec -- end

Test session results, code coverage, and logs:
	/Users/runner/Library/Developer/Xcode/DerivedData/FirebaseAITestApp-bwahwmquzihedieofiheylkbrdnf/Logs/Test/Test-FirebaseAITestApp-SPM-2026.04.29_17-41-21-+0000.xcresult

** TEST EXECUTE FAILED **

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

This pull request addresses critical socket leaks and connection instability identified in the LiveSession implementation. By resolving strong reference cycles and improving cleanup mechanisms, the changes aim to reduce test flakiness and resource exhaustion on CI environments. Additionally, the update introduces improved error handling and connection monitoring to ensure more robust network communication.

Highlights

  • Memory Management: Replaced strong self-captures with weak references in background Tasks within AsyncWebSocket and LiveSessionService to resolve reference cycles.
  • Resource Cleanup: Implemented a deinit mechanism in LiveSession to ensure underlying services are closed when the session object is dropped.
  • WebSocket Reliability: Added a 30-second ping interval to AsyncWebSocket to detect and handle dead connections proactively.
  • Test Robustness: Updated integration tests with consistent do-catch blocks and explicit session closure to prevent resource leaks during test failures.
  • Stream Resiliency: Refactored LiveSessionService.close() to allow WebSocket connection resets without terminating the public responses stream.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Activity
  • Pull request created by andrewheard.
  • Gemini Code Assist bot provided initial guidance.
  • Author shared test logs indicating improved readability despite ongoing test failures.
  • Author requested a summary of the pull request.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces several improvements to the LiveSession and AsyncWebSocket components, focusing on connection stability and resource management. Key changes include the addition of a 30-second ping mechanism in AsyncWebSocket, improved task lifecycle management for receiving and pinging, and a thread-safe streamState in LiveSessionService to better manage the responses stream. Additionally, the integration tests were updated to ensure sessions are properly closed during failures, and the iOS deployment target for the test app was bumped to 16.0. Review feedback highlights potential issues with error propagation in LiveSessionService where the stream might be finished normally before an error is thrown, and suggests adding explicit cancellation checks in the message queue loop.

Comment thread FirebaseAI/Sources/Types/Internal/Live/LiveSessionService.swift Outdated
Comment thread FirebaseAI/Sources/Types/Internal/Live/LiveSessionService.swift Outdated
Comment thread FirebaseAI/Sources/Types/Internal/Live/LiveSessionService.swift
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a ping mechanism to AsyncWebSocket and refactors LiveSessionService to use UnfairLock for thread-safe stream state management. It also bumps the iOS deployment target to 16.0 and improves error handling in integration tests. Feedback includes suggestions to mark message processing methods as nonisolated to reduce context switching, refactor repeated transcript collection logic in tests into a helper method, and adopt the modern Task.sleep(for:) syntax available in iOS 16.

Comment thread FirebaseAI/Sources/Types/Internal/Live/LiveSessionService.swift Outdated
Comment thread FirebaseAI/Tests/TestApp/Tests/Integration/LiveSessionTests.swift Outdated
Comment thread FirebaseAI/Sources/Types/Internal/Live/AsyncWebSocket.swift
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a heartbeat mechanism to AsyncWebSocket via a new ping task and improves lifecycle management for websocket tasks and response streams. In LiveSessionService, stream state is now synchronized using UnfairLock, allowing for stream recreation upon reconnection. The integration tests were updated with do-catch blocks to ensure proper session closure on failure, though it is suggested to refactor this repetitive boilerplate into a helper method for better maintainability. Additionally, the iOS deployment target for the test app was bumped to 16.0.

Comment on lines +132 to +137
do {
text = try await session.collectNextAudioOutputTranscript()
} catch {
await session.close()
throw error
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

The do-catch pattern used here to ensure session.close() is called when an error occurs is repeated across almost every test in this file. While this correctly addresses the socket leak issue, it adds significant boilerplate. To improve maintainability, consider refactoring this into a helper method that wraps the session logic and handles the cleanup in a single place.

@andrewheard andrewheard changed the title [AI] Test "LiveSession Socket Leak Analysis" proposed fixes [AI] LiveSession WebSocket leak fixes May 13, 2026
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