VertexComponentTests.swift 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Copyright 2024 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. @preconcurrency import FirebaseCore
  15. internal import FirebaseCoreExtension
  16. import Foundation
  17. import XCTest
  18. @testable import FirebaseVertexAI
  19. @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
  20. class VertexComponentTests: XCTestCase {
  21. static let projectID = "test-project-id"
  22. static let apiKey = "test-api-key"
  23. static let options = {
  24. let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
  25. gcmSenderID: "00000000000000000-00000000000-000000000")
  26. options.projectID = VertexComponentTests.projectID
  27. options.apiKey = VertexComponentTests.apiKey
  28. return options
  29. }()
  30. static let app = FirebaseApp(instanceWithName: "test", options: options)
  31. let location = "test-location"
  32. let modelName = "test-model-name"
  33. let systemInstruction = ModelContent(role: "system", parts: "test-system-instruction-prompt")
  34. override class func setUp() {
  35. FirebaseApp.configure(options: options)
  36. guard FirebaseApp.app() != nil else {
  37. fatalError("The default app does not exist.")
  38. }
  39. }
  40. /// Test that the objc class is available for the component system to update the user agent.
  41. func testComponentsBeingRegistered() throws {
  42. XCTAssertNotNil(NSClassFromString("FIRVertexAIComponent"))
  43. }
  44. /// Tests that a vertex instance can be created properly using the default Firebase app.
  45. func testVertexInstanceCreation_defaultApp() throws {
  46. let vertex = VertexAI.vertexAI()
  47. XCTAssertNotNil(vertex)
  48. XCTAssertEqual(vertex.firebaseInfo.projectID, VertexComponentTests.projectID)
  49. XCTAssertEqual(vertex.firebaseInfo.apiKey, VertexComponentTests.apiKey)
  50. XCTAssertEqual(vertex.location, "us-central1")
  51. XCTAssertEqual(vertex.apiConfig.service, .vertexAI(endpoint: .firebaseVertexAIProd))
  52. XCTAssertEqual(vertex.apiConfig.service.endpoint, .firebaseVertexAIProd)
  53. XCTAssertEqual(vertex.apiConfig.version, .v1beta)
  54. }
  55. /// Tests that a vertex instance can be created properly using the default Firebase app and custom
  56. /// location.
  57. func testVertexInstanceCreation_defaultApp_customLocation() throws {
  58. let vertex = VertexAI.vertexAI(location: location)
  59. XCTAssertNotNil(vertex)
  60. XCTAssertEqual(vertex.firebaseInfo.projectID, VertexComponentTests.projectID)
  61. XCTAssertEqual(vertex.firebaseInfo.apiKey, VertexComponentTests.apiKey)
  62. XCTAssertEqual(vertex.location, location)
  63. XCTAssertEqual(vertex.apiConfig.service, .vertexAI(endpoint: .firebaseVertexAIProd))
  64. XCTAssertEqual(vertex.apiConfig.service.endpoint, .firebaseVertexAIProd)
  65. XCTAssertEqual(vertex.apiConfig.version, .v1beta)
  66. }
  67. /// Tests that a vertex instance can be created properly.
  68. func testVertexInstanceCreation_customApp() throws {
  69. let vertex = VertexAI.vertexAI(app: VertexComponentTests.app, location: location)
  70. XCTAssertNotNil(vertex)
  71. XCTAssertEqual(vertex.firebaseInfo.projectID, VertexComponentTests.projectID)
  72. XCTAssertEqual(vertex.firebaseInfo.apiKey, VertexComponentTests.apiKey)
  73. XCTAssertEqual(vertex.location, location)
  74. XCTAssertEqual(vertex.apiConfig.service, .vertexAI(endpoint: .firebaseVertexAIProd))
  75. XCTAssertEqual(vertex.apiConfig.service.endpoint, .firebaseVertexAIProd)
  76. XCTAssertEqual(vertex.apiConfig.version, .v1beta)
  77. }
  78. /// Tests that Vertex instances are reused properly.
  79. func testSameAppAndLocation_instanceReused() throws {
  80. let app = try XCTUnwrap(VertexComponentTests.app)
  81. let vertex1 = VertexAI.vertexAI(app: app, location: location)
  82. let vertex2 = VertexAI.vertexAI(app: app, location: location)
  83. // Ensure they're the same instance.
  84. XCTAssert(vertex1 === vertex2)
  85. }
  86. func testSameAppAndDifferentLocation_newInstanceCreated() throws {
  87. let vertex1 = VertexAI.vertexAI(app: VertexComponentTests.app, location: location)
  88. let vertex2 = VertexAI.vertexAI(app: VertexComponentTests.app, location: "differentLocation")
  89. // Ensure they are different instances.
  90. XCTAssert(vertex1 !== vertex2)
  91. }
  92. func testDifferentAppAndSameLocation_newInstanceCreated() throws {
  93. FirebaseApp.configure(name: "test-2", options: VertexComponentTests.options)
  94. let app2 = FirebaseApp(instanceWithName: "test-2", options: VertexComponentTests.options)
  95. addTeardownBlock { await app2.delete() }
  96. let vertex1 = VertexAI.vertexAI(app: VertexComponentTests.app, location: location)
  97. let vertex2 = VertexAI.vertexAI(app: app2, location: location)
  98. XCTAssert(VertexComponentTests.app != app2)
  99. XCTAssert(vertex1 !== vertex2) // Ensure they are different instances.
  100. }
  101. func testDifferentAppAndDifferentLocation_newInstanceCreated() throws {
  102. FirebaseApp.configure(name: "test-2", options: VertexComponentTests.options)
  103. let app2 = FirebaseApp(instanceWithName: "test-2", options: VertexComponentTests.options)
  104. addTeardownBlock { await app2.delete() }
  105. let vertex1 = VertexAI.vertexAI(app: VertexComponentTests.app, location: location)
  106. let vertex2 = VertexAI.vertexAI(app: app2, location: "differentLocation")
  107. XCTAssert(VertexComponentTests.app != app2)
  108. XCTAssert(vertex1 !== vertex2) // Ensure they are different instances.
  109. }
  110. func testSameAppAndDifferentAPI_newInstanceCreated() throws {
  111. let vertex1 = VertexAI.vertexAI(
  112. app: VertexComponentTests.app,
  113. location: location,
  114. apiConfig: APIConfig(service: .vertexAI(endpoint: .firebaseVertexAIProd), version: .v1beta)
  115. )
  116. let vertex2 = VertexAI.vertexAI(
  117. app: VertexComponentTests.app,
  118. location: location,
  119. apiConfig: APIConfig(service: .vertexAI(endpoint: .firebaseVertexAIProd), version: .v1)
  120. )
  121. // Ensure they are different instances.
  122. XCTAssert(vertex1 !== vertex2)
  123. }
  124. /// Test that vertex instances get deallocated.
  125. func testVertexLifecycle() throws {
  126. weak var weakApp: FirebaseApp?
  127. weak var weakVertex: VertexAI?
  128. try autoreleasepool {
  129. let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
  130. gcmSenderID: "00000000000000000-00000000000-000000000")
  131. options.projectID = VertexComponentTests.projectID
  132. options.apiKey = VertexComponentTests.apiKey
  133. let app1 = FirebaseApp(instanceWithName: "transitory app", options: options)
  134. weakApp = try XCTUnwrap(app1)
  135. let vertex = VertexAI(
  136. app: app1,
  137. location: "transitory location",
  138. apiConfig: VertexAI.defaultVertexAIAPIConfig
  139. )
  140. weakVertex = vertex
  141. XCTAssertNotNil(weakVertex)
  142. }
  143. XCTAssertNil(weakApp)
  144. XCTAssertNil(weakVertex)
  145. }
  146. func testModelResourceName_vertexAI() throws {
  147. let app = try XCTUnwrap(VertexComponentTests.app)
  148. let vertex = VertexAI.vertexAI(app: app, location: location)
  149. let model = "test-model-name"
  150. let projectID = vertex.firebaseInfo.projectID
  151. let modelResourceName = vertex.modelResourceName(modelName: model)
  152. let location = try XCTUnwrap(vertex.location)
  153. XCTAssertEqual(
  154. modelResourceName,
  155. "projects/\(projectID)/locations/\(location)/publishers/google/models/\(model)"
  156. )
  157. }
  158. func testModelResourceName_developerAPI_generativeLanguage() throws {
  159. let app = try XCTUnwrap(VertexComponentTests.app)
  160. let apiConfig = APIConfig(service: .developer(endpoint: .generativeLanguage), version: .v1beta)
  161. let vertex = VertexAI.vertexAI(app: app, location: nil, apiConfig: apiConfig)
  162. let model = "test-model-name"
  163. let modelResourceName = vertex.modelResourceName(modelName: model)
  164. XCTAssertEqual(modelResourceName, "models/\(model)")
  165. }
  166. func testModelResourceName_developerAPI_firebaseVertexAI() throws {
  167. let app = try XCTUnwrap(VertexComponentTests.app)
  168. let apiConfig = APIConfig(
  169. service: .developer(endpoint: .firebaseVertexAIStaging),
  170. version: .v1beta
  171. )
  172. let vertex = VertexAI.vertexAI(app: app, location: nil, apiConfig: apiConfig)
  173. let model = "test-model-name"
  174. let projectID = vertex.firebaseInfo.projectID
  175. let modelResourceName = vertex.modelResourceName(modelName: model)
  176. XCTAssertEqual(modelResourceName, "projects/\(projectID)/models/\(model)")
  177. }
  178. func testGenerativeModel_vertexAI() async throws {
  179. let app = try XCTUnwrap(VertexComponentTests.app)
  180. let vertex = VertexAI.vertexAI(app: app, location: location)
  181. let modelResourceName = vertex.modelResourceName(modelName: modelName)
  182. let expectedSystemInstruction = ModelContent(role: nil, parts: systemInstruction.parts)
  183. let generativeModel = vertex.generativeModel(
  184. modelName: modelName,
  185. systemInstruction: systemInstruction
  186. )
  187. XCTAssertEqual(generativeModel.modelResourceName, modelResourceName)
  188. XCTAssertEqual(generativeModel.systemInstruction, expectedSystemInstruction)
  189. XCTAssertEqual(generativeModel.apiConfig, VertexAI.defaultVertexAIAPIConfig)
  190. }
  191. func testGenerativeModel_developerAPI() async throws {
  192. let app = try XCTUnwrap(VertexComponentTests.app)
  193. let apiConfig = APIConfig(
  194. service: .developer(endpoint: .firebaseVertexAIStaging),
  195. version: .v1beta
  196. )
  197. let vertex = VertexAI.vertexAI(app: app, location: nil, apiConfig: apiConfig)
  198. let modelResourceName = vertex.modelResourceName(modelName: modelName)
  199. let expectedSystemInstruction = ModelContent(role: nil, parts: systemInstruction.parts)
  200. let generativeModel = vertex.generativeModel(
  201. modelName: modelName,
  202. systemInstruction: systemInstruction
  203. )
  204. XCTAssertEqual(generativeModel.modelResourceName, modelResourceName)
  205. XCTAssertEqual(generativeModel.systemInstruction, expectedSystemInstruction)
  206. XCTAssertEqual(generativeModel.apiConfig, apiConfig)
  207. }
  208. }