ContextProviderTests.swift 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. // Copyright 2022 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. import Foundation
  15. import FirebaseCore
  16. @testable import FirebaseFunctions
  17. import FirebaseAppCheckInterop
  18. import FirebaseAuthInterop
  19. import FirebaseMessagingInterop
  20. import SharedTestUtilities
  21. import XCTest
  22. class ContextProviderTests: XCTestCase {
  23. let appCheckFake = FIRAppCheckFake()
  24. let appCheckTokenError = FIRAppCheckTokenResultFake(token: "dummy token",
  25. error: NSError(
  26. domain: "testAppCheckError",
  27. code: -1,
  28. userInfo: nil
  29. ))
  30. let appCheckLimitedUseTokenError = FIRAppCheckTokenResultFake(token: "limited use token",
  31. error: NSError(
  32. domain: "testAppCheckError",
  33. code: -1,
  34. userInfo: nil
  35. ))
  36. let appCheckTokenSuccess = FIRAppCheckTokenResultFake(token: "valid_token", error: nil)
  37. let messagingFake = FIRMessagingInteropFake()
  38. func testAsyncContextWithAuth() async throws {
  39. let auth = FIRAuthInteropFake(token: "token", userID: "userID", error: nil)
  40. let provider = FunctionsContextProvider(auth: auth, messaging: messagingFake, appCheck: nil)
  41. let context = try await provider.context(options: nil)
  42. XCTAssertNotNil(context)
  43. XCTAssertEqual(context.authToken, "token")
  44. XCTAssertEqual(context.fcmToken, messagingFake.fcmToken)
  45. }
  46. func testContextWithAuth() async throws {
  47. let auth = FIRAuthInteropFake(token: "token", userID: "userID", error: nil)
  48. let provider = FunctionsContextProvider(auth: auth, messaging: messagingFake, appCheck: nil)
  49. let context = try await provider.context(options: nil)
  50. XCTAssertEqual(context.authToken, "token")
  51. XCTAssertEqual(context.fcmToken, messagingFake.fcmToken)
  52. }
  53. func testAsyncContextWithAuthError() async {
  54. let authError = NSError(domain: "com.functions.tests", code: 4, userInfo: nil)
  55. let auth = FIRAuthInteropFake(token: nil, userID: "userID", error: authError)
  56. let provider = FunctionsContextProvider(auth: auth, messaging: messagingFake, appCheck: nil)
  57. do {
  58. _ = try await provider.context(options: nil)
  59. XCTFail("Expected an error")
  60. } catch {
  61. XCTAssertEqual(error as NSError, authError)
  62. }
  63. }
  64. func testContextWithAuthError() async throws {
  65. let authError = NSError(domain: "com.functions.tests", code: 4, userInfo: nil)
  66. let auth = FIRAuthInteropFake(token: nil, userID: "userID", error: authError)
  67. let provider = FunctionsContextProvider(auth: auth, messaging: messagingFake, appCheck: nil)
  68. do {
  69. _ = try await provider.context(options: nil)
  70. XCTFail("Expected an error")
  71. } catch {
  72. XCTAssertEqual(error as NSError?, authError)
  73. }
  74. }
  75. func testAsyncContextWithoutAuth() async throws {
  76. let provider = FunctionsContextProvider(auth: nil, messaging: nil, appCheck: nil)
  77. let context = try await provider.context(options: nil)
  78. XCTAssertNil(context.authToken)
  79. XCTAssertNil(context.fcmToken)
  80. }
  81. func testContextWithoutAuth() async throws {
  82. let provider = FunctionsContextProvider(auth: nil, messaging: nil, appCheck: nil)
  83. let context = try await provider.context(options: nil)
  84. XCTAssertNil(context.authToken)
  85. XCTAssertNil(context.fcmToken)
  86. }
  87. func testAsyncContextWithAppCheckOnlySuccess() async throws {
  88. appCheckFake.tokenResult = appCheckTokenSuccess
  89. let provider = FunctionsContextProvider(auth: nil, messaging: nil, appCheck: appCheckFake)
  90. let context = try await provider.context(options: nil)
  91. XCTAssertNil(context.authToken)
  92. XCTAssertNil(context.fcmToken)
  93. XCTAssertEqual(context.appCheckToken, appCheckTokenSuccess.token)
  94. }
  95. func testContextWithAppCheckOnlySuccess() async throws {
  96. appCheckFake.tokenResult = appCheckTokenSuccess
  97. let provider = FunctionsContextProvider(auth: nil, messaging: nil, appCheck: appCheckFake)
  98. let context = try await provider.context(options: nil)
  99. XCTAssertNil(context.authToken)
  100. XCTAssertNil(context.fcmToken)
  101. XCTAssertEqual(context.appCheckToken, appCheckTokenSuccess.token)
  102. }
  103. func testAsyncContextWithAppCheckOnlyError() async throws {
  104. appCheckFake.tokenResult = appCheckTokenError
  105. let provider = FunctionsContextProvider(auth: nil, messaging: nil, appCheck: appCheckFake)
  106. let context = try await provider.context(options: nil)
  107. XCTAssertNil(context.authToken)
  108. XCTAssertNil(context.fcmToken)
  109. // Expect placeholder token in the case of App Check error.
  110. XCTAssertEqual(context.appCheckToken, appCheckFake.tokenResult.token)
  111. }
  112. func testAsyncContextWithAppCheckOnlyError_LimitedUseToken() async throws {
  113. appCheckFake.limitedUseTokenResult = appCheckLimitedUseTokenError
  114. let provider = FunctionsContextProvider(auth: nil, messaging: nil, appCheck: appCheckFake)
  115. let context = try await provider.context(options: .init(requireLimitedUseAppCheckTokens: true))
  116. XCTAssertNil(context.authToken)
  117. XCTAssertNil(context.fcmToken)
  118. // Expect placeholder token in the case of App Check error.
  119. XCTAssertEqual(context.limitedUseAppCheckToken, appCheckFake.limitedUseTokenResult.token)
  120. }
  121. func testContextWithAppCheckOnlyError() async throws {
  122. appCheckFake.tokenResult = appCheckTokenError
  123. let provider = FunctionsContextProvider(auth: nil, messaging: nil, appCheck: appCheckFake)
  124. let context = try await provider.context(options: nil)
  125. XCTAssertNil(context.authToken)
  126. XCTAssertNil(context.fcmToken)
  127. // Expect placeholder token in the case of App Check error.
  128. XCTAssertEqual(context.appCheckToken, appCheckFake.tokenResult.token)
  129. }
  130. func testContextWithAppCheckOnlyError_LimitedUseToken() async throws {
  131. appCheckFake.limitedUseTokenResult = appCheckLimitedUseTokenError
  132. let provider = FunctionsContextProvider(auth: nil, messaging: nil, appCheck: appCheckFake)
  133. let context = try await provider
  134. .context(options: HTTPSCallableOptions(requireLimitedUseAppCheckTokens: true))
  135. XCTAssertNil(context.authToken)
  136. XCTAssertNil(context.fcmToken)
  137. // Expect placeholder token in the case of App Check error.
  138. XCTAssertEqual(context.limitedUseAppCheckToken, appCheckFake.limitedUseTokenResult.token)
  139. }
  140. func testAsyncContextWithAppCheckWithoutOptionalMethods() async throws {
  141. let appCheck = AppCheckFakeWithoutOptionalMethods(tokenResult: appCheckTokenSuccess)
  142. let provider = FunctionsContextProvider(auth: nil, messaging: nil, appCheck: appCheck)
  143. let context = try await provider.context(options: .init(requireLimitedUseAppCheckTokens: true))
  144. XCTAssertNil(context.authToken)
  145. XCTAssertNil(context.fcmToken)
  146. XCTAssertNil(context.appCheckToken)
  147. // If the method for limited-use tokens is not implemented, the value should be `nil`:
  148. XCTAssertNil(context.limitedUseAppCheckToken)
  149. }
  150. func testContextWithAppCheckWithoutOptionalMethods() async throws {
  151. let appCheck = AppCheckFakeWithoutOptionalMethods(tokenResult: appCheckTokenSuccess)
  152. let provider = FunctionsContextProvider(auth: nil, messaging: nil, appCheck: appCheck)
  153. let context = try await provider.context(options: .init(requireLimitedUseAppCheckTokens: true))
  154. XCTAssertNil(context.authToken)
  155. XCTAssertNil(context.fcmToken)
  156. XCTAssertNil(context.appCheckToken)
  157. // If the method for limited-use tokens is not implemented, the value should be `nil`:
  158. XCTAssertNil(context.limitedUseAppCheckToken)
  159. }
  160. func testAsyncAllContextsAvailableSuccess() async throws {
  161. appCheckFake.tokenResult = appCheckTokenSuccess
  162. let auth = FIRAuthInteropFake(token: "token", userID: "userID", error: nil)
  163. let provider = FunctionsContextProvider(
  164. auth: auth,
  165. messaging: messagingFake,
  166. appCheck: appCheckFake
  167. )
  168. let context = try await provider.context(options: nil)
  169. XCTAssertEqual(context.authToken, "token")
  170. XCTAssertEqual(context.fcmToken, messagingFake.fcmToken)
  171. XCTAssertEqual(context.appCheckToken, appCheckTokenSuccess.token)
  172. }
  173. func testAllContextsAvailableSuccess() async throws {
  174. appCheckFake.tokenResult = appCheckTokenSuccess
  175. let auth = FIRAuthInteropFake(token: "token", userID: "userID", error: nil)
  176. let provider = FunctionsContextProvider(
  177. auth: auth,
  178. messaging: messagingFake,
  179. appCheck: appCheckFake
  180. )
  181. let context = try await provider.context(options: nil)
  182. XCTAssertEqual(context.authToken, "token")
  183. XCTAssertEqual(context.fcmToken, messagingFake.fcmToken)
  184. XCTAssertEqual(context.appCheckToken, appCheckTokenSuccess.token)
  185. }
  186. func testAsyncAllContextsAuthAndAppCheckError() async {
  187. appCheckFake.tokenResult = appCheckTokenError
  188. let authError = NSError(domain: "com.functions.tests", code: 4, userInfo: nil)
  189. let auth = FIRAuthInteropFake(token: nil, userID: "userID", error: authError)
  190. let provider = FunctionsContextProvider(
  191. auth: auth,
  192. messaging: messagingFake,
  193. appCheck: appCheckFake
  194. )
  195. do {
  196. _ = try await provider.context(options: nil)
  197. XCTFail("Expected an error")
  198. } catch {
  199. XCTAssertEqual(error as NSError, authError)
  200. }
  201. }
  202. func testAllContextsAuthAndAppCheckError() async throws {
  203. appCheckFake.tokenResult = appCheckTokenError
  204. let authError = NSError(domain: "com.functions.tests", code: 4, userInfo: nil)
  205. let auth = FIRAuthInteropFake(token: nil, userID: "userID", error: authError)
  206. let provider = FunctionsContextProvider(
  207. auth: auth,
  208. messaging: messagingFake,
  209. appCheck: appCheckFake
  210. )
  211. do {
  212. _ = try await provider.context(options: nil)
  213. XCTFail("Expected an error")
  214. } catch {
  215. XCTAssertEqual(error as NSError?, authError)
  216. }
  217. }
  218. func testAllContextsAuthAndAppCheckError_LimitedUseToken() async throws {
  219. appCheckFake.limitedUseTokenResult = appCheckLimitedUseTokenError
  220. let authError = NSError(domain: "com.functions.tests", code: 4, userInfo: nil)
  221. let auth = FIRAuthInteropFake(token: nil, userID: "userID", error: authError)
  222. let provider = FunctionsContextProvider(
  223. auth: auth,
  224. messaging: messagingFake,
  225. appCheck: appCheckFake
  226. )
  227. do {
  228. _ = try await provider.context(options: .init(requireLimitedUseAppCheckTokens: true))
  229. XCTFail("Expected an error")
  230. } catch {
  231. XCTAssertEqual(error as NSError?, authError)
  232. }
  233. }
  234. }
  235. // MARK: - Utilities
  236. private class AppCheckFakeWithoutOptionalMethods: NSObject, AppCheckInterop {
  237. let tokenResult: FIRAppCheckTokenResultInterop
  238. init(tokenResult: FIRAppCheckTokenResultInterop) {
  239. self.tokenResult = tokenResult
  240. }
  241. func getToken(forcingRefresh: Bool, completion handler: @escaping AppCheckTokenHandlerInterop) {
  242. handler(tokenResult)
  243. }
  244. func tokenDidChangeNotificationName() -> String { "AppCheckFakeTokenDidChangeNotification" }
  245. func notificationTokenKey() -> String { "AppCheckFakeTokenNotificationKey" }
  246. func notificationAppNameKey() -> String { "AppCheckFakeAppNameNotificationKey" }
  247. }