FPRNetworkTraceTest.m 22 KB

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