SessionGeneratorTests.swift 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  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 SessionGeneratorTests: XCTestCase {
  18. var generator: SessionGenerator!
  19. let validSettings: [String: Any] = [:]
  20. var cache: SettingsCacheClient!
  21. var appInfo: MockApplicationInfo!
  22. var downloader: MockSettingsDownloader!
  23. var remoteSettings: RemoteSettings!
  24. var localOverrideSettings: LocalOverrideSettings!
  25. var sdkDefaultSettings: SDKDefaultSettings!
  26. var sessionSettings: SessionsSettings!
  27. override func setUp() {
  28. // Clear all UserDefaults
  29. if let appDomain = Bundle.main.bundleIdentifier {
  30. UserDefaults.standard.removePersistentDomain(forName: appDomain)
  31. }
  32. appInfo = MockApplicationInfo()
  33. cache = SettingsCache()
  34. cache.removeCache() // just reinstantiating cache isn't enough because of persistence
  35. downloader = MockSettingsDownloader(successResponse: validSettings)
  36. remoteSettings = RemoteSettings(appInfo: appInfo, downloader: downloader, cache: cache)
  37. remoteSettings.updateSettings(currentTime: Date())
  38. localOverrideSettings = LocalOverrideSettings()
  39. sdkDefaultSettings = SDKDefaultSettings()
  40. sessionSettings = SessionsSettings(
  41. appInfo: appInfo,
  42. installations: MockInstallationsProtocol(),
  43. sdkDefaults: sdkDefaultSettings,
  44. localOverrides: localOverrideSettings,
  45. remoteSettings: remoteSettings
  46. )
  47. generator = SessionGenerator(settings: sessionSettings)
  48. }
  49. func isValidSessionID(_ sessionID: String) -> Bool {
  50. if sessionID.count != 32 {
  51. assertionFailure("Session ID isn't 32 characters long")
  52. return false
  53. }
  54. if sessionID.contains("-") {
  55. assertionFailure("Session ID contains a dash")
  56. return false
  57. }
  58. if sessionID.lowercased().compare(sessionID) != ComparisonResult.orderedSame {
  59. assertionFailure("Session ID is not lowercase")
  60. return false
  61. }
  62. return true
  63. }
  64. // This test case isn't important behavior. When Crash and Perf integrate
  65. // with the Sessions SDK, we may want to move to a lazy solution where
  66. // sessionID can never be empty
  67. func test_sessionID_beforeGenerateReturnsNothing() throws {
  68. XCTAssertNil(generator.currentSession)
  69. }
  70. func test_generateNewSessionID_generatesValidID() throws {
  71. let sessionInfo = generator.generateNewSession()
  72. XCTAssert(isValidSessionID(sessionInfo.sessionId))
  73. XCTAssertNil(sessionInfo.previousSessionId)
  74. }
  75. /// Ensures that generating a Session ID multiple times results in the last Session ID being set in the previousSessionID field
  76. func test_generateNewSessionID_rotatesPreviousID() throws {
  77. let firstSessionInfo = generator.generateNewSession()
  78. let firstSessionID = firstSessionInfo.sessionId
  79. XCTAssert(isValidSessionID(firstSessionInfo.sessionId))
  80. XCTAssertNil(firstSessionInfo.previousSessionId)
  81. let secondSessionInfo = generator.generateNewSession()
  82. XCTAssert(isValidSessionID(secondSessionInfo.sessionId))
  83. XCTAssert(isValidSessionID(secondSessionInfo.previousSessionId!))
  84. // Ensure the new lastSessionID is equal to the sessionID from earlier
  85. XCTAssertEqual(secondSessionInfo.previousSessionId, firstSessionID)
  86. }
  87. func test_sessionsNotSampled_AllEventsAllowed() throws {
  88. let someSettings: [String: Any] = [
  89. "cache_duration": 10,
  90. "app_quality": [
  91. "sampling_rate": 1.0,
  92. "session_timeout_seconds": 50,
  93. ],
  94. ]
  95. cache.removeCache()
  96. downloader = MockSettingsDownloader(successResponse: someSettings)
  97. remoteSettings = RemoteSettings(appInfo: appInfo, downloader: downloader, cache: cache)
  98. remoteSettings.updateSettings(currentTime: Date())
  99. sessionSettings = SessionsSettings(
  100. appInfo: appInfo,
  101. installations: MockInstallationsProtocol(),
  102. sdkDefaults: sdkDefaultSettings,
  103. localOverrides: localOverrideSettings,
  104. remoteSettings: remoteSettings
  105. )
  106. let sessionInfo = generator.generateNewSession()
  107. XCTAssertTrue(sessionInfo.shouldDispatchEvents)
  108. }
  109. func test_sessionsSampled_NoEventsAllowed() throws {
  110. let someSettings: [String: Any] = [
  111. "cache_duration": 10,
  112. "app_quality": [
  113. "sampling_rate": 0.0,
  114. "session_timeout_seconds": 50,
  115. ],
  116. ]
  117. cache.removeCache()
  118. downloader = MockSettingsDownloader(successResponse: someSettings)
  119. remoteSettings = RemoteSettings(appInfo: appInfo, downloader: downloader, cache: cache)
  120. remoteSettings.updateSettings(currentTime: Date())
  121. sessionSettings = SessionsSettings(
  122. appInfo: appInfo,
  123. installations: MockInstallationsProtocol(),
  124. sdkDefaults: sdkDefaultSettings,
  125. localOverrides: localOverrideSettings,
  126. remoteSettings: remoteSettings
  127. )
  128. let sessionInfo = generator.generateNewSession()
  129. XCTAssertFalse(sessionInfo.shouldDispatchEvents)
  130. }
  131. }