RemoteSettingsTests.swift 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. //
  2. // Copyright 2022 Google LLC
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. import XCTest
  16. @testable import FirebaseSessions
  17. class RemoteSettingsTests: XCTestCase {
  18. // 2021-11-01 @ 00:00:00 (EST)
  19. let date = Date(timeIntervalSince1970: 1_635_739_200)
  20. let validSettings: [String: Any] = [
  21. "cache_duration": 10,
  22. "app_quality": [
  23. "sessions_enabled": false,
  24. "sampling_rate": 0.5,
  25. "session_timeout_seconds": 10,
  26. ],
  27. ]
  28. let validSettings2: [String: Any] = [
  29. "cache_duration": 20,
  30. "app_quality": [
  31. "sessions_enabled": true,
  32. "sampling_rate": 0.2,
  33. "session_timeout_seconds": 20,
  34. ],
  35. ]
  36. let corruptedJSONString: String = "{{{{ non_key: non\"value {}"
  37. var cache: SettingsCacheClient!
  38. var appInfo: MockApplicationInfo!
  39. var downloader: MockSettingsDownloader!
  40. var settings: RemoteSettings!
  41. override func setUp() {
  42. super.setUp()
  43. appInfo = MockApplicationInfo()
  44. downloader = MockSettingsDownloader(successResponse: validSettings)
  45. cache = SettingsCache()
  46. cache.removeCache() // just reinstantiating cache isn't enough because of persistence
  47. settings = RemoteSettings(appInfo: appInfo, downloader: downloader, cache: cache)
  48. }
  49. func test_noCacheSaved_returnsNilSettings() {
  50. downloader.shouldSucceed = false
  51. settings.updateSettings(currentTime: Date.distantFuture)
  52. XCTAssertTrue(cache.cacheContent.isEmpty)
  53. XCTAssertNil(cache.cacheKey)
  54. XCTAssertNil(settings.sessionsEnabled)
  55. XCTAssertNil(settings.samplingRate)
  56. XCTAssertNil(settings.sessionTimeout)
  57. }
  58. func test_successfulFetch_returnsCachedSettings() {
  59. appInfo.mockAllInfo()
  60. downloader.shouldSucceed = true
  61. settings.updateSettings(currentTime: date)
  62. // Should be same as self.validSettings
  63. XCTAssertFalse(settings.sessionsEnabled!)
  64. XCTAssertEqual(settings.samplingRate, 0.5)
  65. XCTAssertEqual(settings.sessionTimeout, 10)
  66. }
  67. func test_cacheKeyIsNotExpired_stopsFetchFromProceeding() {
  68. // Given
  69. appInfo.mockAllInfo()
  70. downloader.shouldSucceed = true
  71. settings.updateSettings(currentTime: date)
  72. XCTAssertFalse(settings.sessionsEnabled!)
  73. XCTAssertEqual(settings.samplingRate, 0.5)
  74. XCTAssertEqual(settings.sessionTimeout, 10)
  75. // When
  76. // time passed = 5, TTL = 10, time passed < TTL
  77. let now = date.addingTimeInterval(5)
  78. // downloader will return new setting
  79. downloader.successResponse = validSettings2
  80. downloader.shouldSucceed = true
  81. settings.updateSettings(currentTime: now)
  82. // Then
  83. // fetch did not happen, still provide old cached settings
  84. XCTAssertFalse(settings.sessionsEnabled!)
  85. XCTAssertEqual(settings.samplingRate, 0.5)
  86. XCTAssertEqual(settings.sessionTimeout, 10)
  87. }
  88. func test_cacheKeyExpiredFromAppVersion_fetchNewSettingsOrContinueOldSettings() {
  89. // Given
  90. appInfo.mockAllInfo()
  91. downloader.shouldSucceed = true
  92. settings.updateSettings(currentTime: date)
  93. // When
  94. // time passed = 5, TTL = 10, time passed < TTL
  95. let now = date.addingTimeInterval(5)
  96. appInfo.appBuildVersion = "testNewAppBuildVersion"
  97. appInfo.appDisplayVersion = "testNewAppDisplayVersion"
  98. // downloader fails
  99. downloader.shouldSucceed = false
  100. settings.updateSettings(currentTime: now)
  101. // Then
  102. // However, still provide already cached settings
  103. XCTAssertFalse(settings.sessionsEnabled!)
  104. XCTAssertEqual(settings.samplingRate, 0.5)
  105. XCTAssertEqual(settings.sessionTimeout, 10)
  106. // When
  107. // time passed = 5, TTL = 10, time passed < TTL
  108. // downloader succeeds
  109. downloader.successResponse = validSettings2
  110. downloader.shouldSucceed = true
  111. settings.updateSettings(currentTime: now)
  112. // Then
  113. // provide new settings
  114. XCTAssertTrue(settings.sessionsEnabled!)
  115. XCTAssertEqual(settings.samplingRate, 0.2)
  116. XCTAssertEqual(settings.sessionTimeout, 20)
  117. }
  118. func test_cacheKeyExpiredFromTTL_fetchNewSettingsOrContinueOldSettings() {
  119. // Given
  120. appInfo.mockAllInfo()
  121. downloader.shouldSucceed = true
  122. settings.updateSettings(currentTime: date)
  123. // When
  124. // time passed = 11, TTL = 10, tim passed > TTL
  125. let now = date.addingTimeInterval(11)
  126. // downloader fails
  127. downloader.shouldSucceed = false
  128. settings.updateSettings(currentTime: now)
  129. // Then
  130. // However, still provide already cached settings
  131. XCTAssertFalse(settings.sessionsEnabled!)
  132. XCTAssertEqual(settings.samplingRate, 0.5)
  133. XCTAssertEqual(settings.sessionTimeout, 10)
  134. // When
  135. // time passed = 11, TTL = 10, time passed < TTL
  136. // downloader succeeds
  137. downloader.successResponse = validSettings2
  138. downloader.shouldSucceed = true
  139. settings.updateSettings(currentTime: now)
  140. // Then
  141. // provide new settings
  142. XCTAssertTrue(settings.sessionsEnabled!)
  143. XCTAssertEqual(settings.samplingRate, 0.2)
  144. XCTAssertEqual(settings.sessionTimeout, 20)
  145. }
  146. func test_cacheKeyGoogleAppIDChanged_fetchNewSettingsOrReturnDefaults() {
  147. // Given
  148. appInfo.mockAllInfo()
  149. downloader.shouldSucceed = true
  150. settings.updateSettings(currentTime: date)
  151. // When
  152. // change appID
  153. appInfo.appID = "testDifferentGoogleAppID"
  154. // time passed = 5, TTL = 10, time passed < TTL
  155. let now = date.addingTimeInterval(5)
  156. // downloader fails
  157. downloader.shouldSucceed = false
  158. settings.updateSettings(currentTime: now)
  159. // Then
  160. // provide default settings
  161. XCTAssertNil(settings.sessionsEnabled)
  162. XCTAssertNil(settings.samplingRate)
  163. XCTAssertNil(settings.sessionTimeout)
  164. // When
  165. // time passed = 5, TTL = 10, time passed < TTL
  166. // downloader succeeds
  167. downloader.successResponse = validSettings2
  168. downloader.shouldSucceed = true
  169. settings.updateSettings(currentTime: now)
  170. // Then
  171. // provide new settings
  172. XCTAssertTrue(settings.sessionsEnabled!)
  173. XCTAssertEqual(settings.samplingRate, 0.2)
  174. XCTAssertEqual(settings.sessionTimeout, 20)
  175. }
  176. func test_corruptedCache_fetchNewSettingsOrReturnDefaults() {
  177. // Given
  178. appInfo.mockAllInfo()
  179. downloader.shouldSucceed = true
  180. settings.updateSettings(currentTime: date)
  181. XCTAssertFalse(settings.sessionsEnabled!)
  182. XCTAssertEqual(settings.samplingRate, 0.5)
  183. XCTAssertEqual(settings.sessionTimeout, 10)
  184. // When
  185. write(jsonString: corruptedJSONString, isCacheKey: false)
  186. // Then
  187. // should provide default values
  188. XCTAssertNil(settings.sessionsEnabled)
  189. XCTAssertNil(settings.samplingRate)
  190. XCTAssertNil(settings.sessionTimeout)
  191. // When
  192. // time passed = 5, TTL = 10, time passed < TTL
  193. let now = date.addingTimeInterval(5)
  194. downloader.successResponse = validSettings2
  195. downloader.shouldSucceed = true
  196. settings.updateSettings(currentTime: now)
  197. // Then
  198. // Fetch proceeds, provide new settings
  199. XCTAssertTrue(settings.sessionsEnabled!)
  200. XCTAssertEqual(settings.samplingRate, 0.2)
  201. XCTAssertEqual(settings.sessionTimeout, 20)
  202. }
  203. func test_corruptedCacheKey_fetchNewSettingsOrReturnDefaults() {
  204. // Given
  205. appInfo.mockAllInfo()
  206. downloader.shouldSucceed = true
  207. settings.updateSettings(currentTime: date)
  208. XCTAssertFalse(settings.sessionsEnabled!)
  209. XCTAssertEqual(settings.samplingRate, 0.5)
  210. XCTAssertEqual(settings.sessionTimeout, 10)
  211. // When
  212. // cache key is corrupted, and fetch fails
  213. write(jsonString: corruptedJSONString, isCacheKey: true)
  214. downloader.shouldSucceed = false
  215. settings.updateSettings(currentTime: date)
  216. // Then
  217. // should provide default values
  218. XCTAssertNil(settings.sessionsEnabled)
  219. XCTAssertNil(settings.samplingRate)
  220. XCTAssertNil(settings.sessionTimeout)
  221. // When
  222. // time passed = 5, TTL = 10, time passed < TTL
  223. let now = date.addingTimeInterval(5)
  224. downloader.successResponse = validSettings2
  225. downloader.shouldSucceed = true
  226. settings.updateSettings(currentTime: now)
  227. // Then
  228. // Fetch proceeds, provide new settings
  229. XCTAssertTrue(settings.sessionsEnabled!)
  230. XCTAssertEqual(settings.samplingRate, 0.2)
  231. XCTAssertEqual(settings.sessionTimeout, 20)
  232. }
  233. func write(jsonString: String, isCacheKey: Bool) {
  234. let name = isCacheKey ? "firebase-sessions-cache-key" : "firebase-sessions-settings"
  235. UserDefaults.standard.set(jsonString, forKey: name)
  236. }
  237. }