SessionStartEventTests.swift 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  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. #if SWIFT_PACKAGE
  17. import FirebaseSessionsObjC
  18. #endif // SWIFT_PACKAGE
  19. #if SWIFT_PACKAGE
  20. @_implementationOnly import GoogleUtilities_Environment
  21. #else
  22. @_implementationOnly import GoogleUtilities
  23. #endif // SWIFT_PACKAGE
  24. @testable import FirebaseSessions
  25. class SessionStartEventTests: XCTestCase {
  26. var time: MockTimeProvider!
  27. var appInfo: MockApplicationInfo!
  28. override func setUp() {
  29. super.setUp()
  30. time = MockTimeProvider()
  31. appInfo = MockApplicationInfo()
  32. }
  33. var defaultSessionInfo: SessionInfo {
  34. return SessionInfo(
  35. sessionId: "test_session_id",
  36. firstSessionId: "test_first_session_id",
  37. dispatchEvents: true,
  38. sessionIndex: 0
  39. )
  40. }
  41. var thirdSessionInfo: SessionInfo {
  42. return SessionInfo(
  43. sessionId: "test_third_session_id",
  44. firstSessionId: "test_first_session_id",
  45. dispatchEvents: true,
  46. sessionIndex: 2
  47. )
  48. }
  49. /// This function runs the `testCase` twice, once for the proto object stored in
  50. /// the event, and once after encoding and decoding the proto. This is useful for
  51. /// testing cases where the proto hasn't been encoded correctly.
  52. func testProtoAndDecodedProto(sessionEvent: SessionStartEvent,
  53. testCase: (firebase_appquality_sessions_SessionEvent) -> Void) {
  54. let proto = sessionEvent.proto
  55. testCase(proto)
  56. /// If you are getting failures in this test case, and not the one above, the
  57. /// problem likely lies in encoding the proto
  58. let decodedProto = sessionEvent.encodeDecodeEvent()
  59. testCase(decodedProto)
  60. }
  61. func test_init_setsSessionData() {
  62. let event = SessionStartEvent(sessionInfo: thirdSessionInfo, appInfo: appInfo, time: time)
  63. testProtoAndDecodedProto(sessionEvent: event) { proto in
  64. assertEqualProtoString(
  65. proto.session_data.session_id,
  66. expected: "test_third_session_id",
  67. fieldName: "session_id"
  68. )
  69. assertEqualProtoString(
  70. proto.session_data.first_session_id,
  71. expected: "test_first_session_id",
  72. fieldName: "first_session_id"
  73. )
  74. XCTAssertEqual(proto.session_data.session_index, 2)
  75. XCTAssertEqual(proto.session_data.event_timestamp_us, 123)
  76. }
  77. }
  78. func test_init_setsApplicationInfo() {
  79. let event = SessionStartEvent(sessionInfo: defaultSessionInfo, appInfo: appInfo, time: time)
  80. testProtoAndDecodedProto(sessionEvent: event) { proto in
  81. assertEqualProtoString(
  82. proto.application_info.app_id,
  83. expected: MockApplicationInfo.testAppID,
  84. fieldName: "app_id"
  85. )
  86. assertEqualProtoString(
  87. proto.application_info.session_sdk_version,
  88. expected: MockApplicationInfo.testSDKVersion,
  89. fieldName: "session_sdk_version"
  90. )
  91. assertEqualProtoString(
  92. proto.application_info.os_version,
  93. expected: MockApplicationInfo.testOsDisplayVersion,
  94. fieldName: "os_version"
  95. )
  96. assertEqualProtoString(
  97. proto.application_info.apple_app_info.bundle_short_version,
  98. expected: MockApplicationInfo.testAppDisplayVersion,
  99. fieldName: "bundle_short_version"
  100. )
  101. assertEqualProtoString(
  102. proto.application_info.apple_app_info.app_build_version,
  103. expected: MockApplicationInfo.testAppBuildVersion,
  104. fieldName: "app_build_version"
  105. )
  106. assertEqualProtoString(
  107. proto.application_info.device_model,
  108. expected: MockApplicationInfo.testDeviceModel,
  109. fieldName: "device_model"
  110. )
  111. // Ensure we convert the test OS name into the enum.
  112. XCTAssertEqual(
  113. proto.application_info.apple_app_info.os_name,
  114. firebase_appquality_sessions_OsName_IOS
  115. )
  116. }
  117. }
  118. func test_setInstallationID_setsInstallationID() {
  119. let event = SessionStartEvent(sessionInfo: defaultSessionInfo, appInfo: appInfo, time: time)
  120. event.setInstallationID(installationId: "testInstallationID")
  121. testProtoAndDecodedProto(sessionEvent: event) { proto in
  122. assertEqualProtoString(
  123. proto.session_data.firebase_installation_id,
  124. expected: "testInstallationID",
  125. fieldName: "firebase_installation_id"
  126. )
  127. }
  128. }
  129. func test_convertOSName_convertsCorrectly() {
  130. let expectations: [(given: String, expected: firebase_appquality_sessions_OsName)] = [
  131. ("macos", firebase_appquality_sessions_OsName_MACOS),
  132. ("maccatalyst", firebase_appquality_sessions_OsName_MACCATALYST),
  133. ("ios_on_mac", firebase_appquality_sessions_OsName_IOS_ON_MAC),
  134. ("ios", firebase_appquality_sessions_OsName_IOS),
  135. ("tvos", firebase_appquality_sessions_OsName_TVOS),
  136. ("watchos", firebase_appquality_sessions_OsName_WATCHOS),
  137. ("ipados", firebase_appquality_sessions_OsName_IPADOS),
  138. ("something unknown", firebase_appquality_sessions_OsName_UNKNOWN_OSNAME),
  139. ]
  140. expectations.forEach { (given: String, expected: firebase_appquality_sessions_OsName) in
  141. appInfo.osName = given
  142. let event = SessionStartEvent(
  143. sessionInfo: self.defaultSessionInfo,
  144. appInfo: appInfo,
  145. time: time
  146. )
  147. testProtoAndDecodedProto(sessionEvent: event) { proto in
  148. XCTAssertEqual(event.proto.application_info.apple_app_info.os_name, expected)
  149. }
  150. }
  151. }
  152. func test_convertLogEnvironment_convertsCorrectly() {
  153. let expectations: [(given: DevEnvironment,
  154. expected: firebase_appquality_sessions_LogEnvironment)] = [
  155. (.prod, firebase_appquality_sessions_LogEnvironment_LOG_ENVIRONMENT_PROD),
  156. (
  157. .staging,
  158. firebase_appquality_sessions_LogEnvironment_LOG_ENVIRONMENT_STAGING
  159. ),
  160. (
  161. .autopush,
  162. firebase_appquality_sessions_LogEnvironment_LOG_ENVIRONMENT_AUTOPUSH
  163. ),
  164. ]
  165. expectations.forEach { (given: DevEnvironment,
  166. expected: firebase_appquality_sessions_LogEnvironment) in
  167. appInfo.environment = given
  168. let event = SessionStartEvent(
  169. sessionInfo: self.defaultSessionInfo,
  170. appInfo: appInfo,
  171. time: time
  172. )
  173. XCTAssertEqual(event.proto.application_info.log_environment, expected)
  174. }
  175. }
  176. func test_dataCollectionState_defaultIsUnknown() {
  177. let event = SessionStartEvent(sessionInfo: defaultSessionInfo, appInfo: appInfo, time: time)
  178. testProtoAndDecodedProto(sessionEvent: event) { proto in
  179. XCTAssertEqual(
  180. proto.session_data.data_collection_status.performance,
  181. firebase_appquality_sessions_DataCollectionState_COLLECTION_SDK_NOT_INSTALLED
  182. )
  183. XCTAssertEqual(
  184. proto.session_data.data_collection_status.crashlytics,
  185. firebase_appquality_sessions_DataCollectionState_COLLECTION_SDK_NOT_INSTALLED
  186. )
  187. }
  188. }
  189. func test_newtworkInfo_onlyPresentWhenPerformanceInstalled() {
  190. let mockNetworkInfo = MockNetworkInfo()
  191. mockNetworkInfo.networkType = .mobile
  192. // Mobile Subtypes are always empty on non-iOS platforms, and
  193. // Performance doesn't support those platforms anyways
  194. #if os(iOS) && !targetEnvironment(macCatalyst)
  195. mockNetworkInfo.mobileSubtype = CTRadioAccessTechnologyHSUPA
  196. #else
  197. mockNetworkInfo.mobileSubtype = ""
  198. #endif
  199. appInfo.networkInfo = mockNetworkInfo
  200. let event = SessionStartEvent(sessionInfo: defaultSessionInfo, appInfo: appInfo, time: time)
  201. // These fields will not be filled in when Crashlytics is installed
  202. event.set(subscriber: .Crashlytics, isDataCollectionEnabled: true, appInfo: appInfo)
  203. // They should also not be filled in when Performance data collection is disabled
  204. event.set(subscriber: .Performance, isDataCollectionEnabled: false, appInfo: appInfo)
  205. // Expect empty because Crashlytics is installed, but not Perf
  206. testProtoAndDecodedProto(sessionEvent: event) { proto in
  207. XCTAssertEqual(
  208. event.proto.application_info.apple_app_info.network_connection_info.network_type,
  209. firebase_appquality_sessions_NetworkConnectionInfo_NetworkType_DUMMY
  210. )
  211. XCTAssertEqual(
  212. event.proto.application_info.apple_app_info.network_connection_info.mobile_subtype,
  213. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE
  214. )
  215. assertEqualProtoString(
  216. proto.application_info.apple_app_info.mcc_mnc,
  217. expected: "",
  218. fieldName: "mcc_mnc"
  219. )
  220. }
  221. // These fields will only be filled in when the Perf SDK is installed
  222. event.set(subscriber: .Performance, isDataCollectionEnabled: true, appInfo: appInfo)
  223. // Now the field should be set with the real thing
  224. testProtoAndDecodedProto(sessionEvent: event) { proto in
  225. XCTAssertEqual(
  226. event.proto.application_info.apple_app_info.network_connection_info.network_type,
  227. firebase_appquality_sessions_NetworkConnectionInfo_NetworkType_MOBILE
  228. )
  229. // Mobile Subtypes are always empty on non-iOS platforms, and
  230. // Performance doesn't support those platforms anyways
  231. #if os(iOS) && !targetEnvironment(macCatalyst)
  232. XCTAssertEqual(
  233. event.proto.application_info.apple_app_info.network_connection_info.mobile_subtype,
  234. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_HSUPA
  235. )
  236. #else
  237. XCTAssertEqual(
  238. event.proto.application_info.apple_app_info.network_connection_info.mobile_subtype,
  239. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE
  240. )
  241. #endif
  242. assertEqualProtoString(
  243. proto.application_info.apple_app_info.mcc_mnc,
  244. expected: "",
  245. fieldName: "mcc_mnc"
  246. )
  247. }
  248. }
  249. func test_convertNetworkType_convertsCorrectly() {
  250. let expectations: [(
  251. given: GULNetworkType,
  252. expected: firebase_appquality_sessions_NetworkConnectionInfo_NetworkType
  253. )] = [
  254. (
  255. .WIFI,
  256. firebase_appquality_sessions_NetworkConnectionInfo_NetworkType_WIFI
  257. ),
  258. (
  259. .mobile,
  260. firebase_appquality_sessions_NetworkConnectionInfo_NetworkType_MOBILE
  261. ),
  262. (
  263. .none,
  264. firebase_appquality_sessions_NetworkConnectionInfo_NetworkType_DUMMY
  265. ),
  266. ]
  267. expectations.forEach { (
  268. given: GULNetworkType,
  269. expected: firebase_appquality_sessions_NetworkConnectionInfo_NetworkType
  270. ) in
  271. let mockNetworkInfo = MockNetworkInfo()
  272. mockNetworkInfo.networkType = given
  273. appInfo.networkInfo = mockNetworkInfo
  274. let event = SessionStartEvent(
  275. sessionInfo: self.defaultSessionInfo,
  276. appInfo: appInfo,
  277. time: time
  278. )
  279. // These fields will only be filled in when the Perf SDK is installed
  280. event.set(subscriber: .Performance, isDataCollectionEnabled: true, appInfo: appInfo)
  281. testProtoAndDecodedProto(sessionEvent: event) { proto in
  282. XCTAssertEqual(
  283. event.proto.application_info.apple_app_info.network_connection_info.network_type,
  284. expected
  285. )
  286. }
  287. }
  288. }
  289. /// Following tests can be run only in iOS environment
  290. #if os(iOS) && !targetEnvironment(macCatalyst)
  291. func test_convertMobileSubtype_convertsCorrectlyPreOS14() {
  292. let expectations: [(
  293. given: String,
  294. expected: firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype
  295. )] = [
  296. (
  297. CTRadioAccessTechnologyGPRS,
  298. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_GPRS
  299. ),
  300. (
  301. CTRadioAccessTechnologyEdge,
  302. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_EDGE
  303. ),
  304. (
  305. CTRadioAccessTechnologyWCDMA,
  306. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_CDMA
  307. ),
  308. (
  309. CTRadioAccessTechnologyCDMA1x,
  310. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_CDMA
  311. ),
  312. (
  313. CTRadioAccessTechnologyHSDPA,
  314. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_HSDPA
  315. ),
  316. (
  317. CTRadioAccessTechnologyHSUPA,
  318. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_HSUPA
  319. ),
  320. (
  321. CTRadioAccessTechnologyCDMAEVDORev0,
  322. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_EVDO_0
  323. ),
  324. (
  325. CTRadioAccessTechnologyCDMAEVDORevA,
  326. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_EVDO_A
  327. ),
  328. (
  329. CTRadioAccessTechnologyCDMAEVDORevB,
  330. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_EVDO_B
  331. ),
  332. (
  333. CTRadioAccessTechnologyeHRPD,
  334. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_EHRPD
  335. ),
  336. (
  337. CTRadioAccessTechnologyLTE,
  338. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_LTE
  339. ),
  340. (
  341. "random",
  342. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE
  343. ),
  344. ]
  345. expectations
  346. .forEach { (
  347. given: String,
  348. expected: firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype
  349. ) in
  350. let mockNetworkInfo = MockNetworkInfo()
  351. mockNetworkInfo.mobileSubtype = given
  352. appInfo.networkInfo = mockNetworkInfo
  353. let event = SessionStartEvent(
  354. sessionInfo: self.defaultSessionInfo,
  355. appInfo: appInfo,
  356. time: time
  357. )
  358. // These fields will only be filled in when the Perf SDK is installed
  359. event.set(subscriber: .Performance, isDataCollectionEnabled: true, appInfo: appInfo)
  360. testProtoAndDecodedProto(sessionEvent: event) { proto in
  361. XCTAssertEqual(
  362. event.proto.application_info.apple_app_info.network_connection_info.mobile_subtype,
  363. expected
  364. )
  365. }
  366. }
  367. }
  368. #endif
  369. #if os(iOS) && !targetEnvironment(macCatalyst)
  370. @available(iOS 14.1, *)
  371. func test_convertMobileSubtype_convertsCorrectlyPostOS14() {
  372. let expectations: [(
  373. given: String,
  374. expected: firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype
  375. )] = [
  376. (
  377. CTRadioAccessTechnologyGPRS,
  378. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_GPRS
  379. ),
  380. (
  381. CTRadioAccessTechnologyEdge,
  382. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_EDGE
  383. ),
  384. (
  385. CTRadioAccessTechnologyWCDMA,
  386. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_CDMA
  387. ),
  388. (
  389. CTRadioAccessTechnologyCDMA1x,
  390. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_CDMA
  391. ),
  392. (
  393. CTRadioAccessTechnologyHSDPA,
  394. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_HSDPA
  395. ),
  396. (
  397. CTRadioAccessTechnologyHSUPA,
  398. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_HSUPA
  399. ),
  400. (
  401. CTRadioAccessTechnologyCDMAEVDORev0,
  402. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_EVDO_0
  403. ),
  404. (
  405. CTRadioAccessTechnologyCDMAEVDORevA,
  406. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_EVDO_A
  407. ),
  408. (
  409. CTRadioAccessTechnologyCDMAEVDORevB,
  410. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_EVDO_B
  411. ),
  412. (
  413. CTRadioAccessTechnologyeHRPD,
  414. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_EHRPD
  415. ),
  416. (
  417. CTRadioAccessTechnologyLTE,
  418. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_LTE
  419. ),
  420. (
  421. CTRadioAccessTechnologyNRNSA,
  422. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_NR
  423. ),
  424. (
  425. CTRadioAccessTechnologyNR,
  426. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_NR
  427. ),
  428. (
  429. "random",
  430. firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype_UNKNOWN_MOBILE_SUBTYPE
  431. ),
  432. ]
  433. expectations
  434. .forEach { (
  435. given: String,
  436. expected: firebase_appquality_sessions_NetworkConnectionInfo_MobileSubtype
  437. ) in
  438. let mockNetworkInfo = MockNetworkInfo()
  439. mockNetworkInfo.mobileSubtype = given
  440. appInfo.networkInfo = mockNetworkInfo
  441. let event = SessionStartEvent(
  442. sessionInfo: self.defaultSessionInfo,
  443. appInfo: appInfo,
  444. time: time
  445. )
  446. // These fields will only be filled in when the Perf SDK is installed
  447. event.set(subscriber: .Performance, isDataCollectionEnabled: true, appInfo: appInfo)
  448. testProtoAndDecodedProto(sessionEvent: event) { proto in
  449. XCTAssertEqual(
  450. event.proto.application_info.apple_app_info.network_connection_info.mobile_subtype,
  451. expected
  452. )
  453. }
  454. }
  455. }
  456. #endif
  457. }