FPRNetworkTraceTest.m 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  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/Common/FPRConstants.h"
  16. #import "FirebasePerformance/Sources/Configurations/FPRConfigurations+Private.h"
  17. #import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
  18. #import "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags+Private.h"
  19. #import "FirebasePerformance/Sources/Configurations/FPRRemoteConfigFlags.h"
  20. #import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace+Private.h"
  21. #import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
  22. #import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
  23. #import "FirebasePerformance/Tests/Unit/Configurations/FPRFakeRemoteConfig.h"
  24. #import "FirebasePerformance/Tests/Unit/FPRTestCase.h"
  25. #import "FirebasePerformance/Tests/Unit/FPRTestUtils.h"
  26. #import <OCMock/OCMock.h>
  27. @interface FPRNetworkTraceTest : FPRTestCase
  28. @property(nonatomic) NSURLRequest *testURLRequest;
  29. @end
  30. @implementation FPRNetworkTraceTest
  31. - (void)setUp {
  32. [super setUp];
  33. NSURL *URL = [NSURL URLWithString:@"https://abc.com"];
  34. _testURLRequest = [NSURLRequest requestWithURL:URL];
  35. FIRPerformance *performance = [FIRPerformance sharedInstance];
  36. [performance setDataCollectionEnabled:YES];
  37. }
  38. - (void)tearDown {
  39. [super tearDown];
  40. FIRPerformance *performance = [FIRPerformance sharedInstance];
  41. [performance setDataCollectionEnabled:NO];
  42. }
  43. - (void)testInit {
  44. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  45. XCTAssertNotNil(trace);
  46. }
  47. /**
  48. * Validates that the object creation fails for invalid URLs.
  49. */
  50. - (void)testInitWithNonHttpURL {
  51. NSURL *URL = [NSURL URLWithString:@"ftp://abc.com"];
  52. NSURLRequest *sampleURLRequest = [NSURLRequest requestWithURL:URL];
  53. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:sampleURLRequest];
  54. XCTAssertNil(trace);
  55. }
  56. /**
  57. * Validates that the object creation fails for malformed URLs.
  58. */
  59. - (void)testMalformedURL {
  60. NSURL *URL = [NSURL URLWithString:@"htp://abc.com"];
  61. NSURLRequest *sampleURLRequest = [NSURLRequest requestWithURL:URL];
  62. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:sampleURLRequest];
  63. XCTAssertNil(trace);
  64. }
  65. /**
  66. * Validates that the object creation fails for a non URL.
  67. */
  68. - (void)testNonURL {
  69. NSURL *URL = [NSURL URLWithString:@"Iamtheherooftheuniverse"];
  70. NSURLRequest *sampleURLRequest = [NSURLRequest requestWithURL:URL];
  71. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:sampleURLRequest];
  72. XCTAssertNil(trace);
  73. }
  74. /**
  75. * Validates that the object creation fails for nil URLs.
  76. */
  77. - (void)testNilURL {
  78. NSString *URLString = nil;
  79. NSURL *URL = [NSURL URLWithString:URLString];
  80. NSURLRequest *sampleURLRequest = [NSURLRequest requestWithURL:URL];
  81. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:sampleURLRequest];
  82. XCTAssertNil(trace);
  83. }
  84. /**
  85. * Validates that the object creation fails for empty URLs.
  86. */
  87. - (void)testEmptyURL {
  88. NSURL *URL = [NSURL URLWithString:@""];
  89. NSURLRequest *sampleURLRequest = [NSURLRequest requestWithURL:URL];
  90. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:sampleURLRequest];
  91. XCTAssertNil(trace);
  92. }
  93. #pragma mark - Network Trace creation tests.
  94. /** Validates if trace creation fails when SDK flag is disabled in remote config. */
  95. - (void)testTraceCreationWhenSDKFlagDisabled {
  96. FPRConfigurations *configurations = [FPRConfigurations sharedInstance];
  97. FPRFakeRemoteConfig *remoteConfig = [[FPRFakeRemoteConfig alloc] init];
  98. FPRRemoteConfigFlags *configFlags =
  99. [[FPRRemoteConfigFlags alloc] initWithRemoteConfig:(FIRRemoteConfig *)remoteConfig];
  100. configurations.remoteConfigFlags = configFlags;
  101. NSData *valueData = [@"false" dataUsingEncoding:NSUTF8StringEncoding];
  102. FIRRemoteConfigValue *value =
  103. [[FIRRemoteConfigValue alloc] initWithData:valueData source:FIRRemoteConfigSourceRemote];
  104. [remoteConfig.configValues setObject:value forKey:@"fpr_enabled"];
  105. // Trigger the RC config fetch
  106. remoteConfig.lastFetchTime = nil;
  107. configFlags.appStartConfigFetchDelayInSeconds = 0.0;
  108. [configFlags update];
  109. XCTAssertNil([[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest]);
  110. }
  111. /** Validates if trace creation succeeds when SDK flag is enabled in remote config. */
  112. - (void)testTraceCreationWhenSDKFlagEnabled {
  113. FPRConfigurations *configurations = [FPRConfigurations sharedInstance];
  114. FPRFakeRemoteConfig *remoteConfig = [[FPRFakeRemoteConfig alloc] init];
  115. FPRRemoteConfigFlags *configFlags =
  116. [[FPRRemoteConfigFlags alloc] initWithRemoteConfig:(FIRRemoteConfig *)remoteConfig];
  117. configurations.remoteConfigFlags = configFlags;
  118. NSUserDefaults *userDefaults = [[NSUserDefaults alloc] init];
  119. configFlags.userDefaults = userDefaults;
  120. NSString *configKey = [NSString stringWithFormat:@"%@.%@", kFPRConfigPrefix, @"fpr_enabled"];
  121. [userDefaults setObject:@(TRUE) forKey:configKey];
  122. XCTAssertNotNil([[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest]);
  123. }
  124. /** Validates if trace creation fails when SDK flag is enabled in remote config, but data collection
  125. * disabled. */
  126. - (void)testTraceCreationWhenSDKFlagEnabledWithDataCollectionDisabled {
  127. [[FIRPerformance sharedInstance] setDataCollectionEnabled:NO];
  128. FPRConfigurations *configurations = [FPRConfigurations sharedInstance];
  129. FPRFakeRemoteConfig *remoteConfig = [[FPRFakeRemoteConfig alloc] init];
  130. FPRRemoteConfigFlags *configFlags =
  131. [[FPRRemoteConfigFlags alloc] initWithRemoteConfig:(FIRRemoteConfig *)remoteConfig];
  132. configurations.remoteConfigFlags = configFlags;
  133. NSData *valueData = [@"true" dataUsingEncoding:NSUTF8StringEncoding];
  134. FIRRemoteConfigValue *value =
  135. [[FIRRemoteConfigValue alloc] initWithData:valueData source:FIRRemoteConfigSourceRemote];
  136. [remoteConfig.configValues setObject:value forKey:@"fpr_enabled"];
  137. XCTAssertNil([[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest]);
  138. }
  139. #pragma mark - Other Network Trace related tests.
  140. /**
  141. * Validates that the object creation succeeds for long URLs and returns a valid trimmed URL.
  142. */
  143. - (void)testInitWithVeryLongURL {
  144. NSString *domainString = @"https://thelongesturlusedtotestifitisgettingdropped.com";
  145. NSString *appendString = @"/thelongesturlusedtotestifitisgettingdroppedpath";
  146. NSString *URLString = domainString;
  147. NSInteger numberOfAppends = 0;
  148. // Create a long URL which exceed the limit.
  149. while (URLString.length < kFPRMaxURLLength) {
  150. URLString = [URLString stringByAppendingString:appendString];
  151. ++numberOfAppends;
  152. }
  153. URLString = [URLString stringByAppendingString:@"?param=value"];
  154. NSURLRequest *sampleURLRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:URLString]];
  155. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:sampleURLRequest];
  156. XCTAssertNotNil(trace);
  157. // Expected lenght of the URL should be the domainLength, number of times path was appended which
  158. // does not make the length go beyond the max limit.
  159. NSInteger expectedLength = domainString.length + (numberOfAppends - 1) * appendString.length;
  160. XCTAssertEqual(trace.trimmedURLString.length, expectedLength);
  161. }
  162. /**
  163. * Validates the process of checkpointing and the time that is stored for a checkpoint.
  164. */
  165. - (void)testCheckpointStates {
  166. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  167. [trace start];
  168. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  169. NSDictionary<NSString *, NSNumber *> *states = [trace checkpointStates];
  170. XCTAssertEqual(states.count, 1);
  171. NSString *key = [@(FPRNetworkTraceCheckpointStateInitiated) stringValue];
  172. NSNumber *value = [states objectForKey:key];
  173. NSTimeInterval now = [[NSDate date] timeIntervalSince1970];
  174. // Validate if the event had occurred less than a millisecond ago.
  175. XCTAssertLessThan(now - [value doubleValue], .001);
  176. }
  177. /**
  178. * Validates if checkpointing of the same state is not honored.
  179. */
  180. - (void)testCheckpointingAgain {
  181. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  182. [trace start];
  183. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  184. NSTimeInterval firstCheckpointTime = [[NSDate date] timeIntervalSince1970];
  185. NSString *key = [@(FPRNetworkTraceCheckpointStateInitiated) stringValue];
  186. NSDictionary<NSString *, NSNumber *> *statesAfterFirstCheckpoint = [trace checkpointStates];
  187. NSNumber *firstValue = [statesAfterFirstCheckpoint objectForKey:key];
  188. NSTimeInterval firstInitiatedTime = [firstValue doubleValue];
  189. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  190. NSTimeInterval secondCheckpointTime = [[NSDate date] timeIntervalSince1970];
  191. NSDictionary<NSString *, NSNumber *> *statesAfterSecondCheckpoint = [trace checkpointStates];
  192. NSNumber *secondValue = [statesAfterSecondCheckpoint objectForKey:key];
  193. NSTimeInterval secondInitiatedTime = [secondValue doubleValue];
  194. NSDictionary<NSString *, NSNumber *> *states = [trace checkpointStates];
  195. XCTAssertEqual(states.count, 1);
  196. // Validate if the first checkpoint occured before the second checkpoint time.
  197. XCTAssertLessThan(firstCheckpointTime, secondCheckpointTime);
  198. // Validate if the time has not changed even after rec checkpointing.
  199. XCTAssertEqual(firstInitiatedTime, secondInitiatedTime);
  200. }
  201. - (void)testCheckpointStatesBeforeStarting {
  202. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  203. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  204. NSDictionary<NSString *, NSNumber *> *states = [trace checkpointStates];
  205. XCTAssertEqual(states.count, 0);
  206. }
  207. /**
  208. * Validates a successfully completed request for its checkpoints and data fetched out of the
  209. * response.
  210. */
  211. - (void)testDidCompleteRequestWithValidResponse {
  212. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  213. [trace start];
  214. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  215. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  216. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  217. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.testURLRequest.URL
  218. statusCode:200
  219. HTTPVersion:@"HTTP/1.1"
  220. headerFields:headerFields];
  221. NSString *string = @"Successful response";
  222. NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
  223. [trace didReceiveData:data];
  224. [trace didCompleteRequestWithResponse:response error:nil];
  225. NSDictionary<NSString *, NSNumber *> *states = [trace checkpointStates];
  226. XCTAssertEqual(states.count, 3);
  227. XCTAssertEqual(trace.responseCode, 200);
  228. XCTAssertEqual(trace.responseSize, string.length);
  229. XCTAssertEqualObjects(trace.responseContentType, @"text/json");
  230. NSString *key = [@(FPRNetworkTraceCheckpointStateResponseCompleted) stringValue];
  231. NSNumber *value = [states objectForKey:key];
  232. XCTAssertNotNil(value);
  233. }
  234. /**
  235. * Validates a failed network request for its checkpoints and data fetched out of the response.
  236. */
  237. - (void)testDidCompleteRequestWithErrorResponse {
  238. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  239. [trace start];
  240. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  241. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  242. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  243. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.testURLRequest.URL
  244. statusCode:404
  245. HTTPVersion:@"HTTP/1.1"
  246. headerFields:headerFields];
  247. NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:-200 userInfo:nil];
  248. [trace didReceiveData:[NSData data]];
  249. [trace didCompleteRequestWithResponse:response error:error];
  250. NSDictionary<NSString *, NSNumber *> *states = [trace checkpointStates];
  251. XCTAssertEqual(states.count, 3);
  252. XCTAssertEqual(trace.responseCode, 404);
  253. XCTAssertEqual(trace.responseSize, 0);
  254. XCTAssertEqualObjects(trace.responseContentType, @"text/json");
  255. NSString *key = [@(FPRNetworkTraceCheckpointStateResponseCompleted) stringValue];
  256. NSNumber *value = [states objectForKey:key];
  257. XCTAssertNotNil(value);
  258. }
  259. /**
  260. * Validates that the uploaded file size correctly reflect in the NetworkTrace.
  261. */
  262. - (void)testDidUploadFile {
  263. NSBundle *bundle = [FPRTestUtils getBundle];
  264. NSURL *fileURL = [bundle URLForResource:@"smallDownloadFile" withExtension:@""];
  265. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  266. [trace start];
  267. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  268. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  269. [trace didUploadFileWithURL:fileURL];
  270. XCTAssertEqual(trace.requestSize, 26);
  271. XCTAssertEqual(trace.responseSize, 0);
  272. [[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
  273. }
  274. - (void)testCompletedRequest {
  275. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  276. [trace start];
  277. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  278. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  279. [trace didCompleteRequestWithResponse:nil error:nil];
  280. NSDictionary<NSString *, NSNumber *> *states = [trace checkpointStates];
  281. XCTAssertEqual(states.count, 3);
  282. NSString *key = [@(FPRNetworkTraceCheckpointStateResponseCompleted) stringValue];
  283. NSNumber *value = [states objectForKey:key];
  284. XCTAssertNotNil(value);
  285. }
  286. /**
  287. * Validates checkpointing for edge state - Checkpointing after a network request is completed.
  288. */
  289. - (void)testCheckpointAfterCompletedRequest {
  290. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  291. [trace start];
  292. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  293. [trace didCompleteRequestWithResponse:nil error:nil];
  294. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  295. NSDictionary<NSString *, NSNumber *> *states = [trace checkpointStates];
  296. XCTAssertEqual(states.count, 2);
  297. }
  298. - (void)testTimeIntervalBetweenValidStates {
  299. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  300. [trace start];
  301. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  302. sleep(2);
  303. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  304. NSTimeInterval timeDifference =
  305. [trace timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
  306. andState:FPRNetworkTraceCheckpointStateResponseReceived];
  307. XCTAssertLessThan(fabs(timeDifference - 2), 0.2);
  308. }
  309. - (void)testURLTrimmingWithQuery {
  310. NSURL *URL = [NSURL URLWithString:@"https://accounts.google.com/ServiceLogin?service=mail"];
  311. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  312. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  313. XCTAssertEqualObjects(networkTrace.trimmedURLString, @"https://accounts.google.com/ServiceLogin");
  314. }
  315. - (void)testURLTrimmingWithUserNamePasswordAndPort {
  316. NSURL *URL = [NSURL URLWithString:@"https://a:b@ab.com:1000/ServiceLogin?service=mail"];
  317. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  318. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  319. XCTAssertEqualObjects(networkTrace.trimmedURLString, @"https://ab.com:1000/ServiceLogin");
  320. }
  321. - (void)testURLTrimmingWithDeepPath {
  322. NSURL *URL = [NSURL URLWithString:@"https://a:b@ab.com:1000/x/y/z?service=1&really=2"];
  323. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  324. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  325. XCTAssertEqualObjects(networkTrace.trimmedURLString, @"https://ab.com:1000/x/y/z");
  326. }
  327. - (void)testURLTrimmingWithFragments {
  328. NSURL *URL = [NSURL URLWithString:@"https://a:b@ab.com:1000/x#really?service=1&really=2"];
  329. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  330. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  331. XCTAssertEqualObjects(networkTrace.trimmedURLString, @"https://ab.com:1000/x");
  332. }
  333. /** Validate if the trace creation fails when the domain name is beyond max length. */
  334. - (void)testURLMaxLength {
  335. NSString *longString = [@"abd" stringByPaddingToLength:kFPRMaxURLLength + 1
  336. withString:@"-"
  337. startingAtIndex:0];
  338. NSString *urlString = [NSString stringWithFormat:@"https://%@.com", longString];
  339. NSURL *URL = [NSURL URLWithString:urlString];
  340. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  341. XCTAssertNil([[FPRNetworkTrace alloc] initWithURLRequest:URLRequest]);
  342. }
  343. /** Validate if the trimmed URL drops only few sub paths from the URL when the length goes beyond
  344. * the limit.
  345. */
  346. - (void)testURLMaxLengthWithQuerypath {
  347. NSString *longString = [@"abd" stringByPaddingToLength:kFPRMaxURLLength - 20
  348. withString:@"-"
  349. startingAtIndex:0];
  350. NSString *urlString = [NSString stringWithFormat:@"https://%@.com/abcd/efgh/ijkl", longString];
  351. NSURL *URL = [NSURL URLWithString:urlString];
  352. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  353. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  354. XCTAssertNotNil(networkTrace);
  355. XCTAssertEqual(networkTrace.trimmedURLString.length, 1997);
  356. }
  357. /** Validate if the trimmed URL is equal to the URL provided when the length is less than the limit.
  358. */
  359. - (void)testTrimmedURLForShortLengthURLs {
  360. NSString *urlString = @"https://helloworld.com/abcd/efgh/ijkl";
  361. NSURL *URL = [NSURL URLWithString:urlString];
  362. NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL];
  363. FPRNetworkTrace *networkTrace = [[FPRNetworkTrace alloc] initWithURLRequest:URLRequest];
  364. XCTAssertNotNil(networkTrace);
  365. XCTAssertEqual(networkTrace.URLRequest.URL.absoluteString, urlString);
  366. }
  367. /** Validates that every trace contains a session Id. */
  368. - (void)testSessionId {
  369. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  370. [trace start];
  371. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  372. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  373. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  374. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.testURLRequest.URL
  375. statusCode:200
  376. HTTPVersion:@"HTTP/1.1"
  377. headerFields:headerFields];
  378. NSString *string = @"Successful response";
  379. NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
  380. NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
  381. [defaultCenter postNotificationName:UIApplicationDidBecomeActiveNotification
  382. object:[UIApplication sharedApplication]];
  383. [trace didReceiveData:data];
  384. [trace didCompleteRequestWithResponse:response error:nil];
  385. XCTAssertNotNil(trace.sessions);
  386. XCTAssertTrue(trace.sessions.count > 0);
  387. }
  388. /** Validates if a trace contains multiple session Ids on changing app state. */
  389. - (void)testMultipleSessionIds {
  390. FPRNetworkTrace *trace = [[FPRNetworkTrace alloc] initWithURLRequest:self.testURLRequest];
  391. [trace start];
  392. [trace checkpointState:FPRNetworkTraceCheckpointStateInitiated];
  393. [trace checkpointState:FPRNetworkTraceCheckpointStateResponseReceived];
  394. NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
  395. [defaultCenter postNotificationName:UIWindowDidBecomeVisibleNotification
  396. object:[UIApplication sharedApplication]];
  397. [defaultCenter postNotificationName:UIApplicationDidBecomeActiveNotification
  398. object:[UIApplication sharedApplication]];
  399. [defaultCenter postNotificationName:UIApplicationWillEnterForegroundNotification
  400. object:[UIApplication sharedApplication]];
  401. [defaultCenter postNotificationName:UIApplicationWillEnterForegroundNotification
  402. object:[UIApplication sharedApplication]];
  403. NSDictionary<NSString *, NSString *> *headerFields = @{@"Content-Type" : @"text/json"};
  404. NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:self.testURLRequest.URL
  405. statusCode:200
  406. HTTPVersion:@"HTTP/1.1"
  407. headerFields:headerFields];
  408. NSString *string = @"Successful response";
  409. NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
  410. [trace didReceiveData:data];
  411. [trace didCompleteRequestWithResponse:response error:nil];
  412. XCTestExpectation *expectation = [self expectationWithDescription:@"Dummy expectation"];
  413. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)),
  414. dispatch_get_main_queue(), ^{
  415. [expectation fulfill];
  416. XCTAssertNotNil(trace.sessions);
  417. XCTAssertTrue(trace.sessions.count >= 2);
  418. });
  419. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  420. }
  421. @end