FPRGDTLogSamplerTest.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. // Copyright 2020 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 "FirebasePerformance/Sources/Loggers/FPRGDTLogSampler+Private.h"
  16. #import "FirebasePerformance/Sources/Loggers/FPRGDTLogSampler.h"
  17. #import "FirebasePerformance/Sources/Configurations/FPRConfigurations+Private.h"
  18. #import "FirebasePerformance/Sources/FPRProtoUtils.h"
  19. #import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace+Private.h"
  20. #import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
  21. #import "FirebasePerformance/Sources/Loggers/FPRGDTEvent.h"
  22. #import "FirebasePerformance/Sources/Public/FIRTrace.h"
  23. #import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
  24. #import "FirebasePerformance/Sources/Timer/FIRTrace+Private.h"
  25. #import "FirebasePerformance/Tests/Unit/FPRTestCase.h"
  26. #import "FirebasePerformance/Tests/Unit/FPRTestUtils.h"
  27. #import "FirebasePerformance/Tests/Unit/Fakes/FPRFakeConfigurations.h"
  28. #import <GoogleDataTransport/GoogleDataTransport.h>
  29. #import <OCMock/OCMock.h>
  30. @interface FPRGDTLogSamplerTest : FPRTestCase
  31. /** The log sampler object. */
  32. @property(nonatomic) FPRGDTLogSampler *logSampler;
  33. /** Transport object which generates initial GDTCOREvent. */
  34. @property(nonatomic) GDTCORTransport *gdtcctTransport;
  35. /** GDTCOREvent which contains trace event for testing. */
  36. @property(nonatomic) GDTCOREvent *transportTraceEvent;
  37. /** GDTCOREvent which contains network trace event for testing. */
  38. @property(nonatomic) GDTCOREvent *transportNetworkEvent;
  39. /** Fake configurations flags used for overriding configs. */
  40. @property(nonatomic) FPRFakeConfigurations *fakeConfigs;
  41. @end
  42. @implementation FPRGDTLogSamplerTest
  43. - (void)setUp {
  44. [super setUp];
  45. self.appFake.fakeIsDataCollectionDefaultEnabled = YES;
  46. // Mocks log sampling configuration to allow event dispatch.
  47. self.fakeConfigs =
  48. [[FPRFakeConfigurations alloc] initWithSources:FPRConfigurationSourceRemoteConfig];
  49. self.logSampler = [[FPRGDTLogSampler alloc] initWithFlags:self.fakeConfigs
  50. samplingThreshold:0.66];
  51. [self.fakeConfigs setTraceSamplingRate:1.0];
  52. [self.fakeConfigs setNetworkSamplingRate:1.0];
  53. // Defines transport logger for generating log events.
  54. self.gdtcctTransport = [[GDTCORTransport alloc] initWithMappingID:@"462"
  55. transformers:nil
  56. target:kGDTCORTargetCCT];
  57. // Generates sample trace metric.
  58. FPRMSGPerfMetric *tracePerfMetric = [FPRTestUtils createRandomPerfMetric:@"Random"];
  59. self.transportTraceEvent = [self.gdtcctTransport eventForTransport];
  60. self.transportTraceEvent.qosTier = GDTCOREventQosDefault;
  61. self.transportTraceEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:tracePerfMetric];
  62. // Generates sample network trace metric.
  63. NSString *randomAppID = @"RandomID";
  64. FPRMSGPerfMetric *networkTraceMetric = FPRGetPerfMetricMessage(randomAppID);
  65. NSURL *URL = [NSURL URLWithString:@"https://abc.xyz"];
  66. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  67. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  68. [networkTrace start];
  69. [networkTrace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  70. [networkTrace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  71. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  72. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URL
  73. statusCode:200
  74. HTTPVersion:@"HTTP/1.1"
  75. headerFields:headerFields];
  76. [networkTrace didReceiveData:[NSData data]];
  77. [networkTrace didCompleteRequestWithResponse:response error:nil];
  78. // Make sure there are no sessions as they will not be sampled.
  79. networkTrace.activeSessions = [NSMutableArray array];
  80. networkTraceMetric.networkRequestMetric = FPRGetNetworkRequestMetric(networkTrace);
  81. self.transportNetworkEvent = [self.gdtcctTransport eventForTransport];
  82. self.transportNetworkEvent.qosTier = GDTCOREventQosDefault;
  83. self.transportNetworkEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:networkTraceMetric];
  84. }
  85. /** Validates if the object creation is successful. */
  86. - (void)testObjectCreation {
  87. XCTAssertNotNil([[FPRGDTLogSampler alloc] init]);
  88. }
  89. /** Validates if sampling works for valid values of configs. */
  90. - (void)testLogSamplingWithBucketIdentifier {
  91. [self.fakeConfigs setTraceSamplingRate:0.05];
  92. [self.fakeConfigs setNetworkSamplingRate:0.05];
  93. XCTAssertNil([self.logSampler transform:self.transportTraceEvent]);
  94. XCTAssertNil([self.logSampler transform:self.transportNetworkEvent]);
  95. [self.fakeConfigs setTraceSamplingRate:0.65];
  96. [self.fakeConfigs setNetworkSamplingRate:0.65];
  97. XCTAssertNil([self.logSampler transform:self.transportTraceEvent]);
  98. XCTAssertNil([self.logSampler transform:self.transportNetworkEvent]);
  99. [self.fakeConfigs setTraceSamplingRate:0.66];
  100. [self.fakeConfigs setNetworkSamplingRate:0.66];
  101. XCTAssertEqual([self.logSampler transform:self.transportTraceEvent], self.transportTraceEvent);
  102. XCTAssertEqual([self.logSampler transform:self.transportNetworkEvent],
  103. self.transportNetworkEvent);
  104. [self.fakeConfigs setTraceSamplingRate:0.67];
  105. [self.fakeConfigs setNetworkSamplingRate:0.67];
  106. XCTAssertEqual([self.logSampler transform:self.transportTraceEvent], self.transportTraceEvent);
  107. XCTAssertEqual([self.logSampler transform:self.transportNetworkEvent],
  108. self.transportNetworkEvent);
  109. [self.fakeConfigs setTraceSamplingRate:1.0];
  110. [self.fakeConfigs setNetworkSamplingRate:1.0];
  111. XCTAssertEqual([self.logSampler transform:self.transportTraceEvent], self.transportTraceEvent);
  112. XCTAssertEqual([self.logSampler transform:self.transportNetworkEvent],
  113. self.transportNetworkEvent);
  114. }
  115. /** Validates if the trace and network trace event honor different sampling rates. */
  116. - (void)testSamplingWhenTracesAndNetworkSamplingRatesAreDifferent {
  117. [self.fakeConfigs setTraceSamplingRate:0.65];
  118. [self.fakeConfigs setNetworkSamplingRate:0.67];
  119. XCTAssertNil([self.logSampler transform:self.transportTraceEvent]);
  120. XCTAssertEqual([self.logSampler transform:self.transportNetworkEvent],
  121. self.transportNetworkEvent);
  122. [self.fakeConfigs setTraceSamplingRate:0.67];
  123. [self.fakeConfigs setNetworkSamplingRate:0.65];
  124. XCTAssertEqual([self.logSampler transform:self.transportTraceEvent], self.transportTraceEvent);
  125. XCTAssertNil([self.logSampler transform:self.transportNetworkEvent]);
  126. }
  127. /** Validates if sampling works when trace sampling rate is greater than 1. */
  128. - (void)testTraceSamplingWithInvalidNumerator {
  129. [self.fakeConfigs setTraceSamplingRate:2.0];
  130. XCTAssertEqual([self.logSampler transform:self.transportTraceEvent], self.transportTraceEvent);
  131. }
  132. /** Validates if sampling works with trace sampling rate of Zero. */
  133. - (void)testTraceSamplingWithZeroNumerator {
  134. [self.fakeConfigs setTraceSamplingRate:0.0];
  135. XCTAssertNil([self.logSampler transform:self.transportTraceEvent]);
  136. }
  137. /** Validates if sampling works when network sampling rate is greater than 1. */
  138. - (void)testNetworkSamplingWithInvalidNumerator {
  139. [self.fakeConfigs setNetworkSamplingRate:2.0];
  140. XCTAssertEqual([self.logSampler transform:self.transportNetworkEvent],
  141. self.transportNetworkEvent);
  142. }
  143. /** Validates if sampling works with network sampling rate of Zero. */
  144. - (void)testNetworkSamplingWithZeroNumerator {
  145. [self.fakeConfigs setNetworkSamplingRate:0.0];
  146. XCTAssertNil([self.logSampler transform:self.transportNetworkEvent]);
  147. }
  148. /** Validates if the trace event is not dropped if the session is verbose. */
  149. - (void)testTraceSamplingWhenSessionIsVerbose {
  150. [self.fakeConfigs setTraceSamplingRate:0.0];
  151. // Trace is verbose.
  152. FPRMSGPerfMetric *traceMetric = [FPRTestUtils createVerboseRandomPerfMetric:@"Random"];
  153. GDTCOREvent *traceEvent = [self.gdtcctTransport eventForTransport];
  154. traceEvent.qosTier = GDTCOREventQosDefault;
  155. traceEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:traceMetric];
  156. // Trace event will not be dropped.
  157. XCTAssertEqual([self.logSampler transform:traceEvent], traceEvent);
  158. }
  159. /** Validates if the trace event is sampled if the session is not verbose. */
  160. - (void)testTraceSamplingWhenSessionIsNotVerbose {
  161. [self.fakeConfigs setTraceSamplingRate:0.0];
  162. // Trace is non-verbose.
  163. FPRMSGPerfMetric *tracePerfMetric = [FPRTestUtils createRandomPerfMetric:@"random"];
  164. GDTCOREvent *traceEvent = [self.gdtcctTransport eventForTransport];
  165. traceEvent.qosTier = GDTCOREventQosDefault;
  166. traceEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:tracePerfMetric];
  167. // Trace event is dropped because of sampling.
  168. XCTAssertNil([self.logSampler transform:traceEvent]);
  169. }
  170. /** Validates if the network trace event is not sampled if the session is verbose. */
  171. - (void)testNetworkTraceSamplingWhenSessionIsVerbose {
  172. self.appFake.fakeIsDataCollectionDefaultEnabled = YES;
  173. [self.fakeConfigs setNetworkSamplingRate:0.0];
  174. // Network request is verbose.
  175. FPRMSGPerfMetric *networkMetric = FPRGetPerfMetricMessage(@"RandomID");
  176. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  177. NSURLRequest *testURLRequest = [NSURLRequest requestWithURL:URL];
  178. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:testURLRequest];
  179. [networkTrace start];
  180. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:testURLRequest.URL
  181. statusCode:200
  182. HTTPVersion:@"HTTP/1.1"
  183. headerFields:nil];
  184. [networkTrace didCompleteRequestWithResponse:response error:nil];
  185. FPRSessionDetails *details =
  186. [[FPRSessionDetails alloc] initWithSessionId:@"random" options:FPRSessionOptionsGauges];
  187. networkTrace.activeSessions = [[NSMutableArray alloc] initWithObjects:details, nil];
  188. networkMetric.networkRequestMetric = FPRGetNetworkRequestMetric(networkTrace);
  189. GDTCOREvent *networkEvent = [self.gdtcctTransport eventForTransport];
  190. networkEvent.qosTier = GDTCOREventQosDefault;
  191. networkEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:networkMetric];
  192. // Network event will not be dropped.
  193. XCTAssertEqual([self.logSampler transform:networkEvent], networkEvent);
  194. }
  195. /** Validates if the network trace event is sampled if the session is not verbose. */
  196. - (void)testNetworkTraceSamplingWhenSessionIsNotVerbose {
  197. [self.fakeConfigs setNetworkSamplingRate:0.0];
  198. // Network request is not verbose.
  199. FPRMSGPerfMetric *networkMetric = FPRGetPerfMetricMessage(@"RandomID");
  200. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  201. NSURLRequest *testURLRequest = [NSURLRequest requestWithURL:URL];
  202. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:testURLRequest];
  203. [networkTrace start];
  204. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:testURLRequest.URL
  205. statusCode:200
  206. HTTPVersion:@"HTTP/1.1"
  207. headerFields:nil];
  208. [networkTrace didCompleteRequestWithResponse:response error:nil];
  209. // Make sure the session information is empty.
  210. networkTrace.activeSessions = [NSMutableArray array];
  211. networkMetric.networkRequestMetric = FPRGetNetworkRequestMetric(networkTrace);
  212. GDTCOREvent *networkEvent = [self.gdtcctTransport eventForTransport];
  213. networkEvent.qosTier = GDTCOREventQosDefault;
  214. networkEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:networkMetric];
  215. // Network event is dropped because of sampling.
  216. XCTAssertNil([self.logSampler transform:networkEvent]);
  217. }
  218. @end