FPRNetworkTraceTest.m 21 KB

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