FPRProtoUtilsTest.m 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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/FIRPerformance+Internal.h"
  16. #import "FirebasePerformance/Sources/FPRDataUtils.h"
  17. #import "FirebasePerformance/Sources/FPRProtoUtils.h"
  18. #import "FirebasePerformance/Sources/Public/FIRPerformance.h"
  19. #import "FirebasePerformance/Sources/Common/FPRConstants.h"
  20. #import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace+Private.h"
  21. #import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
  22. #import "FirebasePerformance/Sources/Timer/FIRTrace+Internal.h"
  23. #import "FirebasePerformance/Sources/Timer/FIRTrace+Private.h"
  24. #import "FirebasePerformance/Sources/Gauges/CPU/FPRCPUGaugeData.h"
  25. #import "FirebasePerformance/Sources/Gauges/Memory/FPRMemoryGaugeData.h"
  26. #import "FirebasePerformance/Tests/Unit/FPRTestCase.h"
  27. #import <OCMock/OCMock.h>
  28. @interface FPRProtoUtilsTest : FPRTestCase
  29. @end
  30. @implementation FPRProtoUtilsTest
  31. - (void)setUp {
  32. [super setUp];
  33. FIRPerformance *performance = [FIRPerformance sharedInstance];
  34. [performance setDataCollectionEnabled:YES];
  35. }
  36. - (void)tearDown {
  37. [super tearDown];
  38. FIRPerformance *performance = [FIRPerformance sharedInstance];
  39. [performance setDataCollectionEnabled:NO];
  40. }
  41. /** Validates that a PerfMetricMessage creation is successful. */
  42. - (void)testPerfMetricMessageCreation {
  43. NSString *appID = @"RandomAppID";
  44. FPRMSGPerfMetric *perfMetric = FPRGetPerfMetricMessage(appID);
  45. XCTAssertEqualObjects(perfMetric.applicationInfo.googleAppId, appID);
  46. XCTAssertNotNil(perfMetric.applicationInfo);
  47. }
  48. /** Tests if the application information is populated when creating a FPRMSGPerfMetric message. */
  49. - (void)testApplicationInfoMessage {
  50. FPRMSGPerfMetric *event = FPRGetPerfMetricMessage(@"appid");
  51. FPRMSGApplicationInfo *appInfo = event.applicationInfo;
  52. XCTAssertEqual(appInfo.googleAppId, @"appid");
  53. XCTAssertNotNil(appInfo.iosAppInfo.sdkVersion);
  54. XCTAssertNotNil(appInfo.iosAppInfo.bundleShortVersion);
  55. XCTAssertTrue((appInfo.iosAppInfo.mccMnc.length == 0) || (appInfo.iosAppInfo.mccMnc.length == 6));
  56. XCTAssertTrue(appInfo.iosAppInfo.networkConnectionInfo.networkType !=
  57. FPRMSGNetworkConnectionInfo_NetworkType_None);
  58. if (appInfo.iosAppInfo.networkConnectionInfo.networkType ==
  59. FPRMSGNetworkConnectionInfo_NetworkType_Mobile) {
  60. XCTAssertTrue(appInfo.iosAppInfo.networkConnectionInfo.mobileSubtype !=
  61. FPRMSGNetworkConnectionInfo_MobileSubtype_UnknownMobileSubtype);
  62. }
  63. }
  64. /** Validates that ApplicationInfoMessage carries global attributes. */
  65. - (void)testApplicationInfoMessageWithAttributes {
  66. FIRPerformance *performance = [FIRPerformance sharedInstance];
  67. [performance setValue:@"bar" forAttribute:@"foo"];
  68. FPRMSGPerfMetric *event = FPRGetPerfMetricMessage(@"appid");
  69. FPRMSGApplicationInfo *appInfo = event.applicationInfo;
  70. XCTAssertNotNil(appInfo.customAttributes);
  71. XCTAssertEqual(appInfo.customAttributes.allKeys.count, 1);
  72. NSDictionary *attributes = appInfo.customAttributes;
  73. XCTAssertEqual(attributes[@"foo"], @"bar");
  74. [performance removeAttribute:@"foo"];
  75. }
  76. /** Tests if mccMnc validation is catching non numerals. */
  77. - (void)testMccMncOnlyHasNumbers {
  78. NSString *mccMnc = FPRValidatedMccMnc(@"123", @"MKV");
  79. XCTAssertNil(mccMnc);
  80. mccMnc = FPRValidatedMccMnc(@"ABC", @"123");
  81. XCTAssertNil(mccMnc);
  82. }
  83. /** Tests if mccMnc validation is working. */
  84. - (void)testMccMnc {
  85. NSString *mccMnc = FPRValidatedMccMnc(@"123", @"22");
  86. XCTAssertNotNil(mccMnc);
  87. mccMnc = FPRValidatedMccMnc(@"123", @"223");
  88. XCTAssertNotNil(mccMnc);
  89. }
  90. /** Tests if mccMnc validation catches improper lengths. */
  91. - (void)testMccMncLength {
  92. NSString *mccMnc = FPRValidatedMccMnc(@"12", @"22");
  93. XCTAssertNil(mccMnc);
  94. mccMnc = FPRValidatedMccMnc(@"123", @"2");
  95. XCTAssertNil(mccMnc);
  96. }
  97. /** Validates that a valid FIRTrace object to Proto conversion is successful. */
  98. - (void)testTraceMetricMessageCreation {
  99. FIRTrace *trace = [[FIRTrace alloc] initWithName:@"Random"];
  100. [trace start];
  101. [trace startStageNamed:@"1"];
  102. [trace startStageNamed:@"2"];
  103. [trace incrementMetric:@"c1" byInt:2];
  104. [trace setValue:@"bar" forAttribute:@"foo"];
  105. [trace stop];
  106. FPRMSGTraceMetric *traceMetric = FPRGetTraceMetric(trace);
  107. XCTAssertNotNil(traceMetric);
  108. XCTAssertEqualObjects(traceMetric.name, @"Random");
  109. XCTAssertEqual(traceMetric.subtracesArray.count, 2);
  110. XCTAssertEqual(traceMetric.counters.count, 1);
  111. XCTAssertEqualObjects(traceMetric.subtracesArray[0].name, @"1");
  112. XCTAssertEqualObjects(traceMetric.subtracesArray[1].name, @"2");
  113. XCTAssertNotNil(traceMetric.customAttributes);
  114. XCTAssertEqual(traceMetric.customAttributes.allKeys.count, 1);
  115. NSDictionary *attributes = traceMetric.customAttributes;
  116. XCTAssertEqual(attributes[@"foo"], @"bar");
  117. }
  118. /** Validates that a valid FIRTrace object to Proto conversion has required fields. */
  119. - (void)testTraceMetricMessageCreationHasRequiredFields {
  120. FIRTrace *trace = [[FIRTrace alloc] initWithName:@"Random"];
  121. [trace start];
  122. [trace incrementMetric:@"c1" byInt:2];
  123. [trace stop];
  124. FPRMSGTraceMetric *traceMetric = FPRGetTraceMetric(trace);
  125. XCTAssertNotNil(traceMetric);
  126. XCTAssertTrue(traceMetric.hasName);
  127. XCTAssertTrue(traceMetric.hasClientStartTimeUs);
  128. XCTAssertTrue(traceMetric.hasDurationUs);
  129. XCTAssertTrue(traceMetric.hasIsAuto);
  130. }
  131. /** Validates the session details inside trace metric. */
  132. - (void)testTraceMetricMessageHasSessionDetails {
  133. FIRTrace *trace = [[FIRTrace alloc] initWithName:@"Random"];
  134. [trace start];
  135. [trace incrementMetric:@"c1" byInt:2];
  136. FPRSessionDetails *session1 = [[FPRSessionDetails alloc] initWithSessionId:@"a"
  137. options:FPRSessionOptionsNone];
  138. FPRSessionDetails *session2 =
  139. [[FPRSessionDetails alloc] initWithSessionId:@"b" options:FPRSessionOptionsGauges];
  140. trace.activeSessions = [@[ session1, session2 ] mutableCopy];
  141. [trace stop];
  142. FPRMSGTraceMetric *traceMetric = FPRGetTraceMetric(trace);
  143. XCTAssertNotNil(traceMetric);
  144. XCTAssertNotNil(traceMetric.perfSessionsArray);
  145. XCTAssertTrue(traceMetric.perfSessionsArray.count >= 2);
  146. }
  147. /** Validates that an invalid FIRTrace object to Proto conversion is unsuccessful. */
  148. - (void)testTraceMetricMessageCreationForInvalidTrace {
  149. #pragma clang diagnostic push
  150. #pragma clang diagnostic ignored "-Wnonnull"
  151. XCTAssertNil(FPRGetTraceMetric(nil));
  152. #pragma clang diagnostic pop
  153. }
  154. /** Validates that the FPRNetworkTrace object to Proto conversion is successful. */
  155. - (void)testNetworkTraceMetricMessage {
  156. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  157. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  158. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  159. [trace start];
  160. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  161. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  162. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  163. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URLRequest.URL
  164. statusCode:404
  165. HTTPVersion:@"HTTP/1.1"
  166. headerFields:headerFields];
  167. NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-200 userInfo:nil];
  168. [trace didReceiveData:[NSData data]];
  169. [trace didCompleteRequestWithResponse:response error:error];
  170. FPRMSGNetworkRequestMetric *networkMetric = FPRGetNetworkRequestMetric(trace);
  171. XCTAssertEqualObjects(networkMetric.URL, URL.absoluteString);
  172. XCTAssertEqual(networkMetric.HTTPMethod, FPRMSGNetworkRequestMetric_HttpMethod_Get);
  173. XCTAssertEqual(networkMetric.networkClientErrorReason,
  174. FPRMSGNetworkRequestMetric_NetworkClientErrorReason_GenericClientError);
  175. XCTAssertEqual(networkMetric.HTTPResponseCode, 404);
  176. XCTAssertEqualObjects(networkMetric.responseContentType, @"text/json");
  177. }
  178. /** Validates that the FPRNetworkTrace object to Proto conversion has required fields for a valid
  179. * response.
  180. */
  181. - (void)testNetworkTraceMetricMessageHasAllRequiredFields {
  182. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  183. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  184. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  185. [trace start];
  186. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  187. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  188. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  189. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URLRequest.URL
  190. statusCode:404
  191. HTTPVersion:@"HTTP/1.1"
  192. headerFields:headerFields];
  193. NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-200 userInfo:nil];
  194. [trace didReceiveData:[NSData data]];
  195. [trace didCompleteRequestWithResponse:response error:error];
  196. FPRMSGNetworkRequestMetric *networkMetric = FPRGetNetworkRequestMetric(trace);
  197. XCTAssertTrue(networkMetric.hasURL);
  198. XCTAssertTrue(networkMetric.hasClientStartTimeUs);
  199. XCTAssertTrue(networkMetric.hasHTTPMethod);
  200. XCTAssertTrue(networkMetric.hasResponsePayloadBytes);
  201. XCTAssertTrue(networkMetric.hasNetworkClientErrorReason);
  202. XCTAssertTrue(networkMetric.hasHTTPResponseCode);
  203. XCTAssertTrue(networkMetric.hasResponseContentType);
  204. XCTAssertTrue(networkMetric.hasTimeToResponseCompletedUs);
  205. }
  206. /** Validates that an invalid FPRNetworkTrace object to Proto conversion is unsuccessful. */
  207. - (void)testNetworkTraceMetricMessageCreationForInvalidTrace {
  208. #pragma clang diagnostic push
  209. #pragma clang diagnostic ignored "-Wnonnull"
  210. XCTAssertNil(FPRGetNetworkRequestMetric(nil));
  211. #pragma clang diagnostic pop
  212. }
  213. /** Validates that application process state conversion to proto enum type is successful. */
  214. - (void)testApplicationProcessStateConversion {
  215. XCTAssertEqual(FPRMSGApplicationProcessState_Background,
  216. FPRApplicationProcessState(FPRTraceStateBackgroundOnly));
  217. XCTAssertEqual(FPRMSGApplicationProcessState_Foreground,
  218. FPRApplicationProcessState(FPRTraceStateForegroundOnly));
  219. XCTAssertEqual(FPRMSGApplicationProcessState_ForegroundBackground,
  220. FPRApplicationProcessState(FPRTraceStateBackgroundAndForeground));
  221. XCTAssertEqual(FPRMSGApplicationProcessState_ApplicationProcessStateUnknown,
  222. FPRApplicationProcessState(FPRTraceStateUnknown));
  223. // Try with some random value should say the application state is unknown.
  224. XCTAssertEqual(FPRMSGApplicationProcessState_ApplicationProcessStateUnknown,
  225. FPRApplicationProcessState(100));
  226. }
  227. #if __has_include("CoreTelephony/CTTelephonyNetworkInfo.h")
  228. /** Validates if network object creation works. */
  229. - (void)testNetworkInfoObjectCreation {
  230. XCTAssertNotNil(FPRNetworkInfo());
  231. }
  232. #endif
  233. /** Validates if network events are dropped when there is not valid response code. */
  234. - (void)testDroppingNetworkEventsWithInvalidStatusCode {
  235. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  236. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  237. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  238. [trace start];
  239. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  240. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  241. [trace didReceiveData:[NSData data]];
  242. [trace didCompleteRequestWithResponse:nil error:nil];
  243. XCTAssertNil(FPRGetNetworkRequestMetric(trace));
  244. }
  245. /** Validates the session details inside trace metric. */
  246. - (void)testNetworkRequestMetricMessageHasSessionDetails {
  247. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  248. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  249. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  250. [trace start];
  251. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  252. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  253. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  254. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URLRequest.URL
  255. statusCode:404
  256. HTTPVersion:@"HTTP/1.1"
  257. headerFields:headerFields];
  258. NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-200 userInfo:nil];
  259. FPRSessionDetails *session1 = [[FPRSessionDetails alloc] initWithSessionId:@"a"
  260. options:FPRSessionOptionsNone];
  261. FPRSessionDetails *session2 =
  262. [[FPRSessionDetails alloc] initWithSessionId:@"b" options:FPRSessionOptionsGauges];
  263. trace.activeSessions = [@[ session1, session2 ] mutableCopy];
  264. [trace didReceiveData:[NSData data]];
  265. [trace didCompleteRequestWithResponse:response error:error];
  266. FPRMSGNetworkRequestMetric *networkMetric = FPRGetNetworkRequestMetric(trace);
  267. XCTAssertNotNil(networkMetric);
  268. XCTAssertNotNil(networkMetric.perfSessionsArray);
  269. XCTAssertTrue(networkMetric.perfSessionsArray.count >= 2);
  270. }
  271. /** Validates the gauge metric proto packaging works with proper conversions. */
  272. - (void)testMemoryMetricProtoConversion {
  273. NSMutableArray *gauges = [[NSMutableArray alloc] init];
  274. NSDate *date = [NSDate date];
  275. FPRMemoryGaugeData *memoryData = [[FPRMemoryGaugeData alloc] initWithCollectionTime:date
  276. heapUsed:5 * 1024
  277. heapAvailable:10 * 1024];
  278. [gauges addObject:memoryData];
  279. FPRMSGGaugeMetric *gaugeMetric = FPRGetGaugeMetric(gauges, @"abc");
  280. XCTAssertNotNil(gaugeMetric);
  281. XCTAssertEqual(gaugeMetric.cpuMetricReadingsArray_Count, 0);
  282. XCTAssertEqual(gaugeMetric.iosMemoryReadingsArray_Count, 1);
  283. FPRMSGIosMemoryReading *memoryReading = [gaugeMetric.iosMemoryReadingsArray firstObject];
  284. XCTAssertEqual(memoryReading.usedAppHeapMemoryKb, 5);
  285. XCTAssertEqual(memoryReading.freeAppHeapMemoryKb, 10);
  286. }
  287. /** Validates the gauge metric proto packaging works. */
  288. - (void)testGaugeMetricProtoPacking {
  289. NSMutableArray *gauges = [[NSMutableArray alloc] init];
  290. for (int i = 0; i < 5; i++) {
  291. NSDate *date = [NSDate date];
  292. FPRCPUGaugeData *cpuData = [[FPRCPUGaugeData alloc] initWithCollectionTime:date
  293. systemTime:100
  294. userTime:200];
  295. FPRMemoryGaugeData *memoryData = [[FPRMemoryGaugeData alloc] initWithCollectionTime:date
  296. heapUsed:100
  297. heapAvailable:200];
  298. [gauges addObject:cpuData];
  299. [gauges addObject:memoryData];
  300. }
  301. FPRMSGGaugeMetric *gaugeMetric = FPRGetGaugeMetric(gauges, @"abc");
  302. XCTAssertNotNil(gaugeMetric);
  303. XCTAssertEqual(gaugeMetric.cpuMetricReadingsArray_Count, 5);
  304. XCTAssertEqual(gaugeMetric.iosMemoryReadingsArray_Count, 5);
  305. }
  306. /** Validates the gauge metric proto packaging does not create an empty package. */
  307. - (void)testGaugeMetricProtoPackingWithEmptyData {
  308. NSMutableArray *gauges = [[NSMutableArray alloc] init];
  309. FPRMSGGaugeMetric *gaugeMetric1 = FPRGetGaugeMetric(gauges, @"abc");
  310. XCTAssertNil(gaugeMetric1);
  311. FPRMSGGaugeMetric *gaugeMetric2 = FPRGetGaugeMetric(gauges, @"");
  312. XCTAssertNil(gaugeMetric2);
  313. }
  314. /** Validates if the first session is a verbose session for a trace. */
  315. - (void)testOrderingOfSessionsForTrace {
  316. FIRTrace *trace = [[FIRTrace alloc] initWithName:@"Random"];
  317. [trace start];
  318. FPRSessionDetails *session1 = [[FPRSessionDetails alloc] initWithSessionId:@"a"
  319. options:FPRSessionOptionsNone];
  320. FPRSessionDetails *session2 =
  321. [[FPRSessionDetails alloc] initWithSessionId:@"b" options:FPRSessionOptionsGauges];
  322. trace.activeSessions = [@[ session1, session2 ] mutableCopy];
  323. [trace stop];
  324. FPRMSGTraceMetric *traceMetric = FPRGetTraceMetric(trace);
  325. XCTAssertNotNil(traceMetric);
  326. XCTAssertNotNil(traceMetric.perfSessionsArray);
  327. XCTAssertTrue(traceMetric.perfSessionsArray.count >= 2);
  328. FPRMSGPerfSession *perfSession = [traceMetric.perfSessionsArray firstObject];
  329. GPBEnumArray *firstSessionVerbosity = perfSession.sessionVerbosityArray;
  330. XCTAssertEqual([firstSessionVerbosity valueAtIndex:0],
  331. FPRMSGSessionVerbosity_GaugesAndSystemEvents);
  332. XCTAssertEqualObjects(perfSession.sessionId, @"b");
  333. }
  334. /** Validates the verbosity ordering when no sessions are verbose. */
  335. - (void)testOrderingOfNonVerboseSessionsForTrace {
  336. FIRTrace *trace = [[FIRTrace alloc] initWithName:@"Random"];
  337. [trace start];
  338. FPRSessionDetails *session1 = [[FPRSessionDetails alloc] initWithSessionId:@"a"
  339. options:FPRSessionOptionsNone];
  340. FPRSessionDetails *session2 = [[FPRSessionDetails alloc] initWithSessionId:@"b"
  341. options:FPRSessionOptionsNone];
  342. trace.activeSessions = [@[ session1, session2 ] mutableCopy];
  343. [trace stop];
  344. FPRMSGTraceMetric *traceMetric = FPRGetTraceMetric(trace);
  345. XCTAssertNotNil(traceMetric);
  346. XCTAssertNotNil(traceMetric.perfSessionsArray);
  347. XCTAssertTrue(traceMetric.perfSessionsArray.count >= 2);
  348. FPRMSGPerfSession *perfSession = [traceMetric.perfSessionsArray firstObject];
  349. XCTAssertEqualObjects(perfSession.sessionId, @"a");
  350. XCTAssertEqual(perfSession.sessionVerbosityArray_Count, 0);
  351. }
  352. /** Validates if a session is not verbose, do not populate the session verbosity array. */
  353. - (void)testVerbosityArrayEmptyWhenTheSessionIsNotVerbose {
  354. FIRTrace *trace = [[FIRTrace alloc] initWithName:@"Random"];
  355. [trace start];
  356. FPRSessionDetails *session1 = [[FPRSessionDetails alloc] initWithSessionId:@"a"
  357. options:FPRSessionOptionsNone];
  358. trace.activeSessions = [@[ session1 ] mutableCopy];
  359. [trace stop];
  360. FPRMSGTraceMetric *traceMetric = FPRGetTraceMetric(trace);
  361. XCTAssertNotNil(traceMetric);
  362. XCTAssertNotNil(traceMetric.perfSessionsArray);
  363. XCTAssertTrue(traceMetric.perfSessionsArray.count >= 1);
  364. FPRMSGPerfSession *perfSession = [traceMetric.perfSessionsArray firstObject];
  365. XCTAssertEqualObjects(perfSession.sessionId, @"a");
  366. XCTAssertEqual(perfSession.sessionVerbosityArray_Count, 0);
  367. }
  368. /** Validates if the first session is a verbose session for a network trace. */
  369. - (void)testOrderingOfSessionsForNetworkTrace {
  370. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  371. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  372. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  373. [trace start];
  374. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  375. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  376. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  377. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URLRequest.URL
  378. statusCode:404
  379. HTTPVersion:@"HTTP/1.1"
  380. headerFields:headerFields];
  381. NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-200 userInfo:nil];
  382. FPRSessionDetails *session1 = [[FPRSessionDetails alloc] initWithSessionId:@"a"
  383. options:FPRSessionOptionsNone];
  384. FPRSessionDetails *session2 =
  385. [[FPRSessionDetails alloc] initWithSessionId:@"b" options:FPRSessionOptionsGauges];
  386. trace.activeSessions = [@[ session1, session2 ] mutableCopy];
  387. [trace didReceiveData:[NSData data]];
  388. [trace didCompleteRequestWithResponse:response error:error];
  389. FPRMSGNetworkRequestMetric *networkMetric = FPRGetNetworkRequestMetric(trace);
  390. XCTAssertNotNil(networkMetric);
  391. XCTAssertNotNil(networkMetric.perfSessionsArray);
  392. XCTAssertTrue(networkMetric.perfSessionsArray.count >= 2);
  393. FPRMSGPerfSession *perfSession = [networkMetric.perfSessionsArray firstObject];
  394. GPBEnumArray *firstSessionVerbosity = perfSession.sessionVerbosityArray;
  395. XCTAssertEqual([firstSessionVerbosity valueAtIndex:0],
  396. FPRMSGSessionVerbosity_GaugesAndSystemEvents);
  397. XCTAssertEqualObjects(perfSession.sessionId, @"b");
  398. }
  399. /** Validates the verbosity ordering when no sessions are verbose for a network trace. */
  400. - (void)testOrderingOfNonVerboseSessionsForNetworkTrace {
  401. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  402. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  403. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  404. [trace start];
  405. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  406. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  407. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  408. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URLRequest.URL
  409. statusCode:404
  410. HTTPVersion:@"HTTP/1.1"
  411. headerFields:headerFields];
  412. NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-200 userInfo:nil];
  413. FPRSessionDetails *session1 = [[FPRSessionDetails alloc] initWithSessionId:@"a"
  414. options:FPRSessionOptionsNone];
  415. FPRSessionDetails *session2 = [[FPRSessionDetails alloc] initWithSessionId:@"b"
  416. options:FPRSessionOptionsNone];
  417. trace.activeSessions = [@[ session1, session2 ] mutableCopy];
  418. [trace didReceiveData:[NSData data]];
  419. [trace didCompleteRequestWithResponse:response error:error];
  420. FPRMSGNetworkRequestMetric *networkMetric = FPRGetNetworkRequestMetric(trace);
  421. XCTAssertNotNil(networkMetric);
  422. XCTAssertNotNil(networkMetric.perfSessionsArray);
  423. XCTAssertTrue(networkMetric.perfSessionsArray.count >= 2);
  424. FPRMSGPerfSession *perfSession = [networkMetric.perfSessionsArray firstObject];
  425. XCTAssertEqualObjects(perfSession.sessionId, @"a");
  426. XCTAssertEqual(perfSession.sessionVerbosityArray_Count, 0);
  427. }
  428. /** Validates if a session is not verbose, do not populate the session verbosity array for network
  429. * trace.
  430. */
  431. - (void)testVerbosityArrayEmptyWhenTheSessionIsNotVerboseForNetworkTrace {
  432. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  433. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  434. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  435. [trace start];
  436. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  437. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  438. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  439. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:URLRequest.URL
  440. statusCode:404
  441. HTTPVersion:@"HTTP/1.1"
  442. headerFields:headerFields];
  443. NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-200 userInfo:nil];
  444. FPRSessionDetails *session1 = [[FPRSessionDetails alloc] initWithSessionId:@"a"
  445. options:FPRSessionOptionsNone];
  446. trace.activeSessions = [@[ session1 ] mutableCopy];
  447. [trace didReceiveData:[NSData data]];
  448. [trace didCompleteRequestWithResponse:response error:error];
  449. FPRMSGNetworkRequestMetric *networkMetric = FPRGetNetworkRequestMetric(trace);
  450. XCTAssertNotNil(networkMetric);
  451. XCTAssertNotNil(networkMetric.perfSessionsArray);
  452. XCTAssertTrue(networkMetric.perfSessionsArray.count >= 1);
  453. FPRMSGPerfSession *perfSession = [networkMetric.perfSessionsArray firstObject];
  454. XCTAssertEqualObjects(perfSession.sessionId, @"a");
  455. XCTAssertEqual(perfSession.sessionVerbosityArray_Count, 0);
  456. }
  457. @end