FPRGDTLogSamplerTest.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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/FPRNanoPbUtils.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/FirebasePerformance/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 *gdtfllTransport;
  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.gdtfllTransport = [[GDTCORTransport alloc] initWithMappingID:@"462"
  55. transformers:nil
  56. target:kGDTCORTargetFLL];
  57. // Generates sample trace metric.
  58. firebase_perf_v1_PerfMetric tracePerfMetric = [FPRTestUtils createRandomPerfMetric:@"Random"];
  59. self.transportTraceEvent = [self.gdtfllTransport eventForTransport];
  60. self.transportTraceEvent.qosTier = GDTCOREventQosDefault;
  61. self.transportTraceEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:tracePerfMetric];
  62. // Generates sample network trace metric.
  63. NSString *randomAppID = @"RandomID";
  64. firebase_perf_v1_PerfMetric 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. FPRSetNetworkRequestMetric(&networkTraceMetric, FPRGetNetworkRequestMetric(networkTrace));
  81. self.transportNetworkEvent = [self.gdtfllTransport 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 transformGDTEvent:self.transportTraceEvent]);
  94. XCTAssertNil([self.logSampler transformGDTEvent:self.transportNetworkEvent]);
  95. [self.fakeConfigs setTraceSamplingRate:0.65];
  96. [self.fakeConfigs setNetworkSamplingRate:0.65];
  97. XCTAssertNil([self.logSampler transformGDTEvent:self.transportTraceEvent]);
  98. XCTAssertNil([self.logSampler transformGDTEvent:self.transportNetworkEvent]);
  99. [self.fakeConfigs setTraceSamplingRate:0.66];
  100. [self.fakeConfigs setNetworkSamplingRate:0.66];
  101. XCTAssertEqual([self.logSampler transformGDTEvent:self.transportTraceEvent],
  102. self.transportTraceEvent);
  103. XCTAssertEqual([self.logSampler transformGDTEvent:self.transportNetworkEvent],
  104. self.transportNetworkEvent);
  105. [self.fakeConfigs setTraceSamplingRate:0.67];
  106. [self.fakeConfigs setNetworkSamplingRate:0.67];
  107. XCTAssertEqual([self.logSampler transformGDTEvent:self.transportTraceEvent],
  108. self.transportTraceEvent);
  109. XCTAssertEqual([self.logSampler transformGDTEvent:self.transportNetworkEvent],
  110. self.transportNetworkEvent);
  111. [self.fakeConfigs setTraceSamplingRate:1.0];
  112. [self.fakeConfigs setNetworkSamplingRate:1.0];
  113. XCTAssertEqual([self.logSampler transformGDTEvent:self.transportTraceEvent],
  114. self.transportTraceEvent);
  115. XCTAssertEqual([self.logSampler transformGDTEvent:self.transportNetworkEvent],
  116. self.transportNetworkEvent);
  117. }
  118. /** Validates if the trace and network trace event honor different sampling rates. */
  119. - (void)testSamplingWhenTracesAndNetworkSamplingRatesAreDifferent {
  120. [self.fakeConfigs setTraceSamplingRate:0.65];
  121. [self.fakeConfigs setNetworkSamplingRate:0.67];
  122. XCTAssertNil([self.logSampler transformGDTEvent:self.transportTraceEvent]);
  123. XCTAssertEqual([self.logSampler transformGDTEvent:self.transportNetworkEvent],
  124. self.transportNetworkEvent);
  125. [self.fakeConfigs setTraceSamplingRate:0.67];
  126. [self.fakeConfigs setNetworkSamplingRate:0.65];
  127. XCTAssertEqual([self.logSampler transformGDTEvent:self.transportTraceEvent],
  128. self.transportTraceEvent);
  129. XCTAssertNil([self.logSampler transformGDTEvent:self.transportNetworkEvent]);
  130. }
  131. /** Validates if sampling works when trace sampling rate is greater than 1. */
  132. - (void)testTraceSamplingWithInvalidNumerator {
  133. [self.fakeConfigs setTraceSamplingRate:2.0];
  134. XCTAssertEqual([self.logSampler transformGDTEvent:self.transportTraceEvent],
  135. self.transportTraceEvent);
  136. }
  137. /** Validates if sampling works with trace sampling rate of Zero. */
  138. - (void)testTraceSamplingWithZeroNumerator {
  139. [self.fakeConfigs setTraceSamplingRate:0.0];
  140. XCTAssertNil([self.logSampler transformGDTEvent:self.transportTraceEvent]);
  141. }
  142. /** Validates if sampling works when network sampling rate is greater than 1. */
  143. - (void)testNetworkSamplingWithInvalidNumerator {
  144. [self.fakeConfigs setNetworkSamplingRate:2.0];
  145. XCTAssertEqual([self.logSampler transformGDTEvent:self.transportNetworkEvent],
  146. self.transportNetworkEvent);
  147. }
  148. /** Validates if sampling works with network sampling rate of Zero. */
  149. - (void)testNetworkSamplingWithZeroNumerator {
  150. [self.fakeConfigs setNetworkSamplingRate:0.0];
  151. XCTAssertNil([self.logSampler transformGDTEvent:self.transportNetworkEvent]);
  152. }
  153. /** Validates if the trace event is not dropped if the session is verbose. */
  154. - (void)testTraceSamplingWhenSessionIsVerbose {
  155. [self.fakeConfigs setTraceSamplingRate:0.0];
  156. // Trace is verbose.
  157. firebase_perf_v1_PerfMetric traceMetric = [FPRTestUtils createVerboseRandomPerfMetric:@"Random"];
  158. GDTCOREvent *traceEvent = [self.gdtfllTransport eventForTransport];
  159. traceEvent.qosTier = GDTCOREventQosDefault;
  160. traceEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:traceMetric];
  161. // Trace event will not be dropped.
  162. XCTAssertEqual([self.logSampler transformGDTEvent:traceEvent], traceEvent);
  163. }
  164. /** Validates if the trace event is sampled if the session is not verbose. */
  165. - (void)testTraceSamplingWhenSessionIsNotVerbose {
  166. [self.fakeConfigs setTraceSamplingRate:0.0];
  167. // Trace is non-verbose.
  168. firebase_perf_v1_PerfMetric tracePerfMetric = [FPRTestUtils createRandomPerfMetric:@"random"];
  169. GDTCOREvent *traceEvent = [self.gdtfllTransport eventForTransport];
  170. traceEvent.qosTier = GDTCOREventQosDefault;
  171. traceEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:tracePerfMetric];
  172. // Trace event is dropped because of sampling.
  173. XCTAssertNil([self.logSampler transformGDTEvent:traceEvent]);
  174. }
  175. /** Validates if the network trace event is not sampled if the session is verbose. */
  176. - (void)testNetworkTraceSamplingWhenSessionIsVerbose {
  177. self.appFake.fakeIsDataCollectionDefaultEnabled = YES;
  178. [self.fakeConfigs setNetworkSamplingRate:0.0];
  179. // Network request is verbose.
  180. firebase_perf_v1_PerfMetric networkMetric = FPRGetPerfMetricMessage(@"RandomID");
  181. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  182. NSURLRequest *testURLRequest = [NSURLRequest requestWithURL:URL];
  183. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:testURLRequest];
  184. [networkTrace start];
  185. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:testURLRequest.URL
  186. statusCode:200
  187. HTTPVersion:@"HTTP/1.1"
  188. headerFields:nil];
  189. [networkTrace didCompleteRequestWithResponse:response error:nil];
  190. FPRSessionDetails *details =
  191. [[FPRSessionDetails alloc] initWithSessionId:@"random" options:FPRSessionOptionsGauges];
  192. networkTrace.activeSessions = [[NSMutableArray alloc] initWithObjects:details, nil];
  193. FPRSetNetworkRequestMetric(&networkMetric, FPRGetNetworkRequestMetric(networkTrace));
  194. GDTCOREvent *networkEvent = [self.gdtfllTransport eventForTransport];
  195. networkEvent.qosTier = GDTCOREventQosDefault;
  196. networkEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:networkMetric];
  197. // Network event will not be dropped.
  198. XCTAssertEqual([self.logSampler transformGDTEvent:networkEvent], networkEvent);
  199. }
  200. /** Validates if the network trace event is sampled if the session is not verbose. */
  201. - (void)testNetworkTraceSamplingWhenSessionIsNotVerbose {
  202. [self.fakeConfigs setNetworkSamplingRate:0.0];
  203. // Network request is not verbose.
  204. firebase_perf_v1_PerfMetric networkMetric = FPRGetPerfMetricMessage(@"RandomID");
  205. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  206. NSURLRequest *testURLRequest = [NSURLRequest requestWithURL:URL];
  207. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:testURLRequest];
  208. [networkTrace start];
  209. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:testURLRequest.URL
  210. statusCode:200
  211. HTTPVersion:@"HTTP/1.1"
  212. headerFields:nil];
  213. [networkTrace didCompleteRequestWithResponse:response error:nil];
  214. // Make sure the session information is empty.
  215. networkTrace.activeSessions = [NSMutableArray array];
  216. FPRSetNetworkRequestMetric(&networkMetric, FPRGetNetworkRequestMetric(networkTrace));
  217. GDTCOREvent *networkEvent = [self.gdtfllTransport eventForTransport];
  218. networkEvent.qosTier = GDTCOREventQosDefault;
  219. networkEvent.dataObject = [FPRGDTEvent gdtEventForPerfMetric:networkMetric];
  220. // Network event is dropped because of sampling.
  221. XCTAssertNil([self.logSampler transformGDTEvent:networkEvent]);
  222. }
  223. @end