FIRHeartbeatLoggerTests.m 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. // Copyright 2021 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 <XCTest/XCTest.h>
  15. @import FirebaseCoreInternal;
  16. #import "FirebaseCore/Extension/FIRHeartbeatLogger.h"
  17. @interface FIRHeartbeatLogger (Internal)
  18. - (instancetype)initWithAppID:(NSString *)appID
  19. userAgentProvider:(NSString * (^)(void))userAgentProvider;
  20. @end
  21. @interface FIRHeartbeatLoggerTests : XCTestCase
  22. @property(nonatomic) FIRHeartbeatLogger *heartbeatLogger;
  23. @end
  24. @implementation FIRHeartbeatLoggerTests
  25. + (NSString *)dummyAppID {
  26. return NSStringFromClass([self class]);
  27. }
  28. + (NSString * (^)(void))dummyUserAgentProvider {
  29. return ^NSString * {
  30. return @"dummy_agent";
  31. };
  32. }
  33. + (NSString *)formattedStringForDate:(NSDate *)date {
  34. return [[FIRHeartbeatLoggingTestUtils dateFormatter] stringFromDate:date];
  35. }
  36. - (void)setUp {
  37. _heartbeatLogger =
  38. [[FIRHeartbeatLogger alloc] initWithAppID:[[self class] dummyAppID]
  39. userAgentProvider:[[self class] dummyUserAgentProvider]];
  40. [FIRHeartbeatLoggingTestUtils removeUnderlyingHeartbeatStorageContainersAndReturnError:nil];
  41. }
  42. - (void)tearDown {
  43. [FIRHeartbeatLoggingTestUtils removeUnderlyingHeartbeatStorageContainersAndReturnError:nil];
  44. }
  45. - (void)testDoNotLogMoreThanOnceToday {
  46. // Given
  47. FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger;
  48. NSString *expectedDate = [[self class] formattedStringForDate:[NSDate date]];
  49. // When
  50. [heartbeatLogger log];
  51. [heartbeatLogger log];
  52. // Then
  53. FIRHeartbeatsPayload *heartbeatsPayload = [heartbeatLogger flushHeartbeatsIntoPayload];
  54. [self assertEncodedPayloadHeader:FIRHeaderValueFromHeartbeatsPayload(heartbeatsPayload)
  55. isEqualToPayloadJSON:@{
  56. @"version" : @2,
  57. @"heartbeats" : @[ @{@"agent" : @"dummy_agent", @"dates" : @[ expectedDate ]} ]
  58. }];
  59. }
  60. - (void)testDoNotLogMoreThanOnceToday_AfterFlushing {
  61. // Given
  62. FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger;
  63. NSString *expectedDate = [[self class] formattedStringForDate:[NSDate date]];
  64. // When
  65. [heartbeatLogger log];
  66. FIRHeartbeatsPayload *firstHeartbeatsPayload = [heartbeatLogger flushHeartbeatsIntoPayload];
  67. [heartbeatLogger log];
  68. FIRHeartbeatsPayload *secondHeartbeatsPayload = [heartbeatLogger flushHeartbeatsIntoPayload];
  69. // Then
  70. [self assertEncodedPayloadHeader:FIRHeaderValueFromHeartbeatsPayload(firstHeartbeatsPayload)
  71. isEqualToPayloadJSON:@{
  72. @"version" : @2,
  73. @"heartbeats" : @[ @{@"agent" : @"dummy_agent", @"dates" : @[ expectedDate ]} ]
  74. }];
  75. [self assertHeartbeatsPayloadIsEmpty:secondHeartbeatsPayload];
  76. }
  77. - (void)testFlushing_UsingV1API_WhenHeartbeatsAreStored_ReturnsFIRDailyHeartbeatCodeSome {
  78. // Given
  79. FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger;
  80. // When
  81. [heartbeatLogger log];
  82. FIRDailyHeartbeatCode heartbeatInfoCode = [heartbeatLogger heartbeatCodeForToday];
  83. // Then
  84. XCTAssertEqual(heartbeatInfoCode, FIRDailyHeartbeatCodeSome);
  85. }
  86. - (void)testFlushing_UsingV1API_WhenNoHeartbeatsAreStored_ReturnsFIRDailyHeartbeatCodeNone {
  87. // Given
  88. FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger;
  89. // When
  90. FIRDailyHeartbeatCode heartbeatInfoCode = [heartbeatLogger heartbeatCodeForToday];
  91. // Then
  92. XCTAssertEqual(heartbeatInfoCode, FIRDailyHeartbeatCodeNone);
  93. }
  94. - (void)testFlushing_UsingV2API_WhenHeartbeatsAreStored_ReturnsNonEmptyPayload {
  95. // Given
  96. FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger;
  97. NSString *expectedDate = [[self class] formattedStringForDate:[NSDate date]];
  98. // When
  99. [heartbeatLogger log];
  100. FIRHeartbeatsPayload *heartbeatsPayload = [heartbeatLogger flushHeartbeatsIntoPayload];
  101. // Then
  102. [self assertEncodedPayloadHeader:FIRHeaderValueFromHeartbeatsPayload(heartbeatsPayload)
  103. isEqualToPayloadJSON:@{
  104. @"version" : @2,
  105. @"heartbeats" : @[ @{@"agent" : @"dummy_agent", @"dates" : @[ expectedDate ]} ]
  106. }];
  107. }
  108. - (void)testFlushing_UsingV2API_WhenNoHeartbeatsAreStored_ReturnsEmptyPayload {
  109. // Given
  110. FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger;
  111. // When
  112. FIRHeartbeatsPayload *heartbeatsPayload = [heartbeatLogger flushHeartbeatsIntoPayload];
  113. // Then
  114. [self assertHeartbeatsPayloadIsEmpty:heartbeatsPayload];
  115. }
  116. - (void)testLogAndFlushUsingV1API_AndThenFlushAgainUsingV2API_FlushesHeartbeatInTheFirstFlush {
  117. // Given
  118. FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger;
  119. [heartbeatLogger log];
  120. // When
  121. FIRDailyHeartbeatCode heartbeatInfoCode = [heartbeatLogger heartbeatCodeForToday];
  122. FIRHeartbeatsPayload *heartbeatsPayload = [heartbeatLogger flushHeartbeatsIntoPayload];
  123. // Then
  124. XCTAssertEqual(heartbeatInfoCode, FIRDailyHeartbeatCodeSome);
  125. [self assertHeartbeatsPayloadIsEmpty:heartbeatsPayload];
  126. }
  127. - (void)testLogAndFlushUsingV2API_AndThenFlushAgainUsingV1API_FlushesHeartbeatInTheFirstFlush {
  128. // Given
  129. FIRHeartbeatLogger *heartbeatLogger = self.heartbeatLogger;
  130. NSString *expectedDate = [[self class] formattedStringForDate:[NSDate date]];
  131. [heartbeatLogger log];
  132. // When
  133. FIRHeartbeatsPayload *heartbeatsPayload = [heartbeatLogger flushHeartbeatsIntoPayload];
  134. FIRDailyHeartbeatCode heartbeatInfoCode = [heartbeatLogger heartbeatCodeForToday];
  135. // Then
  136. [self assertEncodedPayloadHeader:FIRHeaderValueFromHeartbeatsPayload(heartbeatsPayload)
  137. isEqualToPayloadJSON:@{
  138. @"version" : @2,
  139. @"heartbeats" : @[ @{@"agent" : @"dummy_agent", @"dates" : @[ expectedDate ]} ]
  140. }];
  141. XCTAssertEqual(heartbeatInfoCode, FIRDailyHeartbeatCodeNone);
  142. }
  143. - (void)testHeartbeatLoggersWithSameIDShareTheSameStorage {
  144. // Given
  145. FIRHeartbeatLogger *heartbeatLogger1 =
  146. [[FIRHeartbeatLogger alloc] initWithAppID:[[self class] dummyAppID]
  147. userAgentProvider:[[self class] dummyUserAgentProvider]];
  148. FIRHeartbeatLogger *heartbeatLogger2 =
  149. [[FIRHeartbeatLogger alloc] initWithAppID:[[self class] dummyAppID]
  150. userAgentProvider:[[self class] dummyUserAgentProvider]];
  151. NSString *expectedDate = [[self class] formattedStringForDate:[NSDate date]];
  152. // When
  153. [heartbeatLogger1 log];
  154. // Then
  155. FIRHeartbeatsPayload *heartbeatsPayload = [heartbeatLogger2 flushHeartbeatsIntoPayload];
  156. [self assertEncodedPayloadHeader:FIRHeaderValueFromHeartbeatsPayload(heartbeatsPayload)
  157. isEqualToPayloadJSON:@{
  158. @"version" : @2,
  159. @"heartbeats" : @[ @{@"agent" : @"dummy_agent", @"dates" : @[ expectedDate ]} ]
  160. }];
  161. [self assertHeartbeatLoggerFlushesEmptyPayload:heartbeatLogger1];
  162. }
  163. - (void)testLoggingAHeartbeatDoesNotDependOnUserAgent {
  164. // Given
  165. __block NSString *dummyUserAgent = @"dummy_agent_1";
  166. __auto_type dummyUserAgentProvider = ^NSString * {
  167. return dummyUserAgent;
  168. };
  169. FIRHeartbeatLogger *heartbeatLogger =
  170. [[FIRHeartbeatLogger alloc] initWithAppID:@"testLoggingAHeartbeatDoesNotDependOnUserAgent"
  171. userAgentProvider:dummyUserAgentProvider];
  172. NSString *expectedDate = [[self class] formattedStringForDate:[NSDate date]];
  173. [heartbeatLogger log];
  174. FIRHeartbeatsPayload *heartbeatsPayload = [heartbeatLogger flushHeartbeatsIntoPayload];
  175. // When
  176. dummyUserAgent = @"dummy_agent_2";
  177. [heartbeatLogger log];
  178. // Then
  179. [self assertEncodedPayloadHeader:FIRHeaderValueFromHeartbeatsPayload(heartbeatsPayload)
  180. isEqualToPayloadJSON:@{
  181. @"version" : @2,
  182. @"heartbeats" : @[ @{@"agent" : @"dummy_agent_1", @"dates" : @[ expectedDate ]} ]
  183. }];
  184. [self assertHeartbeatLoggerFlushesEmptyPayload:heartbeatLogger];
  185. }
  186. #pragma mark - Assertions
  187. - (void)assertEncodedPayloadHeader:(NSString *)payloadHeader
  188. isEqualToPayloadJSON:(NSDictionary *)payloadJSON {
  189. NSData *payloadJSONData = [NSJSONSerialization dataWithJSONObject:payloadJSON
  190. options:NSJSONWritingPrettyPrinted
  191. error:nil];
  192. NSString *payloadJSONString = [[NSString alloc] initWithData:payloadJSONData
  193. encoding:NSUTF8StringEncoding];
  194. [FIRHeartbeatLoggingTestUtils assertEncodedPayloadString:payloadHeader
  195. isEqualToLiteralString:payloadJSONString
  196. withError:nil];
  197. }
  198. - (void)assertHeartbeatsPayloadIsEmpty:(FIRHeartbeatsPayload *)heartbeatsPayload {
  199. XCTAssertNil(FIRHeaderValueFromHeartbeatsPayload(heartbeatsPayload));
  200. }
  201. - (void)assertHeartbeatLoggerFlushesEmptyPayload:(FIRHeartbeatLogger *)heartbeatLogger {
  202. FIRHeartbeatsPayload *heartbeatsPayload = [heartbeatLogger flushHeartbeatsIntoPayload];
  203. [self assertHeartbeatsPayloadIsEmpty:heartbeatsPayload];
  204. }
  205. @end