From 7d431b4faf53838ae15795dd6a4dbc11f7bb8a2a Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Thu, 15 Jan 2026 15:41:06 -0800 Subject: [PATCH 1/2] [AI] Add an implicit caching unit test --- .../GenerativeModelVertexAICachingTests.swift | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 FirebaseAI/Tests/Unit/GenerativeModelVertexAICachingTests.swift diff --git a/FirebaseAI/Tests/Unit/GenerativeModelVertexAICachingTests.swift b/FirebaseAI/Tests/Unit/GenerativeModelVertexAICachingTests.swift new file mode 100644 index 00000000000..a9bc72f63ed --- /dev/null +++ b/FirebaseAI/Tests/Unit/GenerativeModelVertexAICachingTests.swift @@ -0,0 +1,80 @@ +// Copyright 2026 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import FirebaseAppCheckInterop +import FirebaseAuthInterop +import FirebaseCore +import XCTest + +@testable import FirebaseAILogic + +@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) +final class GenerativeModelImplicitCachingTests: XCTestCase { + let testPrompt = "What sorts of questions can I ask you?" + let testModelName = "test-model" + let testModelResourceName = + "projects/test-project-id/locations/test-location/publishers/google/models/test-model" + let apiConfig = FirebaseAI.defaultVertexAIAPIConfig + + let vertexSubdirectory = "mock-responses/vertexai" + + var urlSession: URLSession! + var model: GenerativeModel! + + override func setUp() async throws { + let configuration = URLSessionConfiguration.default + configuration.protocolClasses = [MockURLProtocol.self] + urlSession = try XCTUnwrap(URLSession(configuration: configuration)) + model = GenerativeModel( + modelName: testModelName, + modelResourceName: testModelResourceName, + firebaseInfo: GenerativeModelTestUtil.testFirebaseInfo(), + apiConfig: apiConfig, + tools: nil, + requestOptions: RequestOptions(), + urlSession: urlSession + ) + } + + override func tearDown() { + MockURLProtocol.requestHandler = nil + } + + func testGenerateContent_success_implicitCaching() async throws { + MockURLProtocol + .requestHandler = try GenerativeModelTestUtil.httpRequestHandler( + forResource: "unary-success-implicit-caching", + withExtension: "json", + subdirectory: vertexSubdirectory + ) + + let response = try await model.generateContent(testPrompt) + + XCTAssertEqual(response.candidates.count, 1) + let candidate = try XCTUnwrap(response.candidates.first) + let finishReason = try XCTUnwrap(candidate.finishReason) + XCTAssertEqual(finishReason, .stop) + + let usageMetadata = try XCTUnwrap(response.usageMetadata) + XCTAssertEqual(usageMetadata.promptTokenCount, 12013) + XCTAssertEqual(usageMetadata.candidatesTokenCount, 15) + XCTAssertEqual(usageMetadata.totalTokenCount, 12101) + + // Validate implicit caching fields + XCTAssertEqual(usageMetadata.cachedContentTokenCount, 11243) + XCTAssertEqual(usageMetadata.promptTokensDetails.count, 1) + XCTAssertEqual(usageMetadata.promptTokensDetails[0].modality, .text) + XCTAssertEqual(usageMetadata.promptTokensDetails[0].tokenCount, 12013) + } +} From 9dc17413fbf9ebb69e4721909f3257a3bff263ae Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Thu, 15 Jan 2026 15:47:17 -0800 Subject: [PATCH 2/2] review --- .../Tests/Unit/GenerativeModelVertexAICachingTests.swift | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/FirebaseAI/Tests/Unit/GenerativeModelVertexAICachingTests.swift b/FirebaseAI/Tests/Unit/GenerativeModelVertexAICachingTests.swift index a9bc72f63ed..50074f6d49a 100644 --- a/FirebaseAI/Tests/Unit/GenerativeModelVertexAICachingTests.swift +++ b/FirebaseAI/Tests/Unit/GenerativeModelVertexAICachingTests.swift @@ -74,7 +74,9 @@ final class GenerativeModelImplicitCachingTests: XCTestCase { // Validate implicit caching fields XCTAssertEqual(usageMetadata.cachedContentTokenCount, 11243) XCTAssertEqual(usageMetadata.promptTokensDetails.count, 1) - XCTAssertEqual(usageMetadata.promptTokensDetails[0].modality, .text) - XCTAssertEqual(usageMetadata.promptTokensDetails[0].tokenCount, 12013) + let detail = try XCTUnwrap(usageMetadata.promptTokensDetails.first) + XCTAssertEqual(detail.modality, .text) + XCTAssertEqual(detail.tokenCount, 12013) + XCTAssertEqual(usageMetadata.thoughtsTokenCount, 73) } }