FPRNSURLConnectionInstrumentTest.m 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  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 "FirebasePerformance/Tests/Unit/Instruments/FPRNSURLConnectionInstrumentTestDelegates.h"
  15. #import <XCTest/XCTest.h>
  16. #import "FirebasePerformance/Sources/Configurations/FPRConfigurations+Private.h"
  17. #import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
  18. #import "FirebasePerformance/Sources/FPRClient.h"
  19. #import "FirebasePerformance/Sources/Instrumentation/Network/FPRNSURLConnectionInstrument.h"
  20. #import "FirebasePerformance/Sources/Public/FIRPerformance.h"
  21. #import "FirebasePerformance/Tests/Unit/FPRTestCase.h"
  22. #import "FirebasePerformance/Tests/Unit/Server/FPRHermeticTestServer.h"
  23. @interface FPRNSURLConnectionInstrumentTest : FPRTestCase
  24. /** Test server to create connections to. */
  25. @property(nonatomic) FPRHermeticTestServer *testServer;
  26. @end
  27. @implementation FPRNSURLConnectionInstrumentTest
  28. - (void)setUp {
  29. [super setUp];
  30. FIRPerformance *performance = [FIRPerformance sharedInstance];
  31. [performance setDataCollectionEnabled:YES];
  32. self.testServer = [[FPRHermeticTestServer alloc] init];
  33. [self.testServer registerTestPaths];
  34. [self.testServer start];
  35. }
  36. - (void)tearDown {
  37. [super tearDown];
  38. FIRPerformance *performance = [FIRPerformance sharedInstance];
  39. [performance setDataCollectionEnabled:NO];
  40. [self.testServer stop];
  41. self.testServer = nil;
  42. }
  43. /** Waits for the server connection to finish by giving a block to run just before a response is
  44. * sent.
  45. *
  46. * @param block A block to run just after the server response is sent.
  47. */
  48. - (void)waitAndRunBlockAfterResponse:(void (^)(id self,
  49. GCDWebServerRequest *_Nonnull request,
  50. GCDWebServerResponse *_Nonnull response))block {
  51. __block BOOL loopingMainThread = YES;
  52. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  53. dispatch_semaphore_t sema = dispatch_semaphore_create(0);
  54. __weak id weakSelf = self;
  55. self.testServer.responseCompletedBlock =
  56. ^(GCDWebServerRequest *_Nonnull request, GCDWebServerResponse *_Nonnull response) {
  57. block(weakSelf, request, response);
  58. dispatch_semaphore_signal(sema);
  59. };
  60. XCTAssertEqual(
  61. dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC)), 0);
  62. loopingMainThread = NO;
  63. });
  64. // This is necessary because the FPRHermeticTestServer callbacks occur on the main thread.
  65. while (loopingMainThread) {
  66. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
  67. }
  68. }
  69. /** Tests calling +sendAsynchronousRequest:queue:completionHandler: is wrapped and calls
  70. * through.
  71. */
  72. - (void)testSendAsynchronousRequestQueueCompletionHandler {
  73. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  74. [instrument registerInstrumentors];
  75. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler was run"];
  76. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"test"];
  77. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  78. NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  79. [NSURLConnection
  80. sendAsynchronousRequest:request
  81. queue:queue
  82. completionHandler:^(NSURLResponse *_Nullable response, NSData *_Nullable data,
  83. NSError *_Nullable connectionError) {
  84. XCTAssertNil(connectionError);
  85. XCTAssertGreaterThan(data.length, 0);
  86. [expectation fulfill];
  87. }];
  88. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  89. [instrument deregisterInstrumentors];
  90. }
  91. /** Tests calling +sendAsynchronousRequest:queue:completionHandler: is wrapped and calls
  92. * through, even with a nil completionHandler.
  93. */
  94. - (void)testSendAsynchronousRequestQueueWithNilCompletionHandler {
  95. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  96. [instrument registerInstrumentors];
  97. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"test"];
  98. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  99. NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  100. #pragma clang diagnostic push
  101. #pragma clang diagnostic ignored "-Wnonnull"
  102. [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:nil];
  103. #pragma clang diagnostic pop
  104. // Wait for a moment to ensure that the request has gone through.
  105. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  106. GCDWebServerResponse *_Nonnull response) {
  107. XCTAssertEqualObjects(request.URL.absoluteString, URL.absoluteString);
  108. XCTAssertEqual(response.statusCode, 200);
  109. }];
  110. [instrument deregisterInstrumentors];
  111. }
  112. /** Tests calling -initWithRequest:delegate: is wrapped and calls through. */
  113. - (void)testInitWithRequestDelegate {
  114. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  115. [instrument registerInstrumentors];
  116. NSURLRequest *request = [NSURLRequest requestWithURL:self.testServer.serverURL];
  117. [self.testServer stop];
  118. FPRNSURLConnectionCompleteTestDelegate *delegate =
  119. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  120. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  121. XCTAssertNotNil(connection);
  122. [connection start];
  123. // Only let it check for a connection for a half second.
  124. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
  125. XCTAssertTrue(delegate.connectionDidFailWithErrorCalled);
  126. [self.testServer start];
  127. [instrument deregisterInstrumentors];
  128. }
  129. /** Tests calling -initWithRequest:delegate: is wrapped and calls through for NSOperation based
  130. * requests.
  131. */
  132. - (void)testInitWithOperationRequestDelegate {
  133. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  134. [instrument registerInstrumentors];
  135. NSURLRequest *request = [NSURLRequest requestWithURL:self.testServer.serverURL];
  136. [self.testServer stop];
  137. FPRNSURLConnectionOperationTestDelegate *delegate =
  138. [[FPRNSURLConnectionOperationTestDelegate alloc] init];
  139. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  140. XCTAssertNotNil(connection);
  141. [connection start];
  142. // Only let it check for a connection for a half second.
  143. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
  144. XCTAssertTrue(delegate.connectionDidFailWithErrorCalled);
  145. [self.testServer start];
  146. [instrument deregisterInstrumentors];
  147. }
  148. /** Tests calling -initWithRequest:delegate: is wrapped and calls through with nil delegate. */
  149. - (void)testInitWithRequestAndNilDelegate {
  150. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  151. [instrument registerInstrumentors];
  152. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:self.testServer.serverURL];
  153. [request setTimeoutInterval:10.0];
  154. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
  155. delegate:nil
  156. startImmediately:NO];
  157. XCTAssertNotNil(connection);
  158. [connection start];
  159. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  160. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  161. GCDWebServerResponse *_Nonnull response) {
  162. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  163. }];
  164. [instrument deregisterInstrumentors];
  165. }
  166. /** Tests calling -initWithRequest:delegate:startImmediately: doesn't install a delegate. */
  167. - (void)testInitWithRequestDelegateStartImmediately {
  168. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  169. [instrument registerInstrumentors];
  170. NSURLRequest *request = [NSURLRequest requestWithURL:self.testServer.serverURL];
  171. [self.testServer stop];
  172. FPRNSURLConnectionCompleteTestDelegate *delegate =
  173. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  174. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
  175. delegate:delegate
  176. startImmediately:NO];
  177. XCTAssertNotNil(connection);
  178. [connection start];
  179. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  180. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.5]];
  181. XCTAssertTrue(delegate.connectionDidFailWithErrorCalled);
  182. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  183. [self.testServer start];
  184. [instrument deregisterInstrumentors];
  185. }
  186. /** Tests calling +connectionWithRequest:delegate: calls already wrapped methods. */
  187. - (void)testConnectionWithRequestDelegate {
  188. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  189. [instrument registerInstrumentors];
  190. NSURLRequest *request = [NSURLRequest requestWithURL:self.testServer.serverURL];
  191. FPRNSURLConnectionCompleteTestDelegate *delegate =
  192. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  193. NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:delegate];
  194. [connection start];
  195. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  196. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  197. GCDWebServerResponse *_Nonnull response) {
  198. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  199. }];
  200. [instrument deregisterInstrumentors];
  201. }
  202. /** Tests calling -start is wrapped and calls through. */
  203. - (void)testStart {
  204. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  205. [instrument registerInstrumentors];
  206. NSURLRequest *request = [NSURLRequest requestWithURL:self.testServer.serverURL];
  207. FPRNSURLConnectionCompleteTestDelegate *delegate =
  208. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  209. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  210. XCTAssertNotNil(connection);
  211. [connection start];
  212. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  213. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  214. GCDWebServerResponse *_Nonnull response) {
  215. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  216. }];
  217. [instrument deregisterInstrumentors];
  218. }
  219. /** Tests calling -start through startImmediately: is wrapped and calls through. */
  220. - (void)testStartThroughStartImmediately {
  221. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  222. [instrument registerInstrumentors];
  223. NSURLRequest *request = [NSURLRequest requestWithURL:self.testServer.serverURL];
  224. FPRNSURLConnectionCompleteTestDelegate *delegate =
  225. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  226. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  227. XCTAssertNotNil(connection);
  228. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  229. [connection start];
  230. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  231. GCDWebServerResponse *_Nonnull response) {
  232. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  233. }];
  234. [instrument deregisterInstrumentors];
  235. }
  236. /** Tests calling -cancel is wrapped and calls through. */
  237. - (void)testCancel {
  238. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  239. [instrument registerInstrumentors];
  240. NSURLRequest *request = [NSURLRequest requestWithURL:self.testServer.serverURL];
  241. FPRNSURLConnectionCompleteTestDelegate *delegate =
  242. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  243. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  244. XCTAssertNotNil(connection);
  245. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  246. [connection start];
  247. [connection cancel];
  248. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  249. [instrument deregisterInstrumentors];
  250. }
  251. #pragma mark - Delegate methods
  252. /** Tests calling -connection:didFailWithError: is wrapped and calls through. */
  253. - (void)testConnectionDidFailWithError {
  254. self.appFake.fakeIsDataCollectionDefaultEnabled = YES;
  255. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  256. [instrument registerInstrumentors];
  257. NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://nonurl/"]];
  258. [self.testServer stop];
  259. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.2]];
  260. FPRNSURLConnectionCompleteTestDelegate *delegate =
  261. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  262. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  263. [connection start];
  264. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  265. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
  266. XCTAssertTrue(delegate.connectionDidFailWithErrorCalled);
  267. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  268. [self.testServer start];
  269. [instrument deregisterInstrumentors];
  270. }
  271. /** Tests calling -connection:willSendRequest:redirectResponse: is wrapped and calls through.*/
  272. - (void)testConnectionWillSendRequestRedirectResponse {
  273. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  274. [instrument registerInstrumentors];
  275. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testRedirect"];
  276. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  277. FPRNSURLConnectionCompleteTestDelegate *delegate =
  278. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  279. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  280. [connection start];
  281. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  282. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  283. GCDWebServerResponse *_Nonnull response) {
  284. XCTAssertTrue(delegate.connectionWillSendRequestRedirectResponseCalled);
  285. }];
  286. [instrument deregisterInstrumentors];
  287. }
  288. /** Tests calling -connection:didReceiveResponse: is wrapped and calls through. */
  289. - (void)testConnectionDidReceiveResponse {
  290. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  291. [instrument registerInstrumentors];
  292. NSURLRequest *request = [NSURLRequest requestWithURL:self.testServer.serverURL];
  293. FPRNSURLConnectionCompleteTestDelegate *delegate =
  294. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  295. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  296. [connection start];
  297. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  298. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  299. GCDWebServerResponse *_Nonnull response) {
  300. XCTAssertTrue(delegate.connectionDidReceiveResponseCalled);
  301. }];
  302. [instrument deregisterInstrumentors];
  303. }
  304. /** Tests calling -connection:didReceiveData: is wrapped and calls through. */
  305. - (void)testConnectionDidReceiveData {
  306. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  307. [instrument registerInstrumentors];
  308. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testBigDownload"];
  309. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
  310. FPRNSURLConnectionDidReceiveDataDelegate *delegate =
  311. [[FPRNSURLConnectionDidReceiveDataDelegate alloc] init];
  312. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  313. [connection start];
  314. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  315. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  316. GCDWebServerResponse *_Nonnull response) {
  317. XCTAssertTrue(delegate.connectionDidReceiveDataCalled);
  318. }];
  319. [instrument deregisterInstrumentors];
  320. }
  321. /** Tests calling -connection:didSendBodyData:totalBytesWritten:totalBytesExpectedToWrite: is
  322. * wrapped and calls through.
  323. */
  324. - (void)testConnectionDidSendBodyDataTotalBytesWrittenTotalBytesExpectedToWrite {
  325. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  326. [instrument registerInstrumentors];
  327. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testUpload"];
  328. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
  329. request.HTTPMethod = @"POST";
  330. NSURL *fileURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"smallDownloadFile"
  331. withExtension:@""];
  332. request.HTTPBody = [NSData dataWithContentsOfURL:fileURL];
  333. FPRNSURLConnectionCompleteTestDelegate *delegate =
  334. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  335. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  336. [connection start];
  337. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  338. FPRNetworkTrace *networkTrace = [FPRNetworkTrace networkTraceFromObject:connection];
  339. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  340. GCDWebServerResponse *_Nonnull response) {
  341. XCTAssertTrue(
  342. delegate.connectionDidSendBodyDataTotalBytesWrittenTotalBytesExpectedToWriteCalled);
  343. XCTAssert(networkTrace.requestSize > 0);
  344. XCTAssert(
  345. [networkTrace
  346. timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
  347. andState:FPRNetworkTraceCheckpointStateRequestCompleted] > 0);
  348. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  349. }];
  350. [instrument deregisterInstrumentors];
  351. }
  352. /** Tests calling -connectionDidFinishLoading: is wrapped and calls through. */
  353. - (void)testConnectionDidFinishLoading {
  354. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  355. [instrument registerInstrumentors];
  356. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testDownload"];
  357. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  358. FPRNSURLConnectionDidReceiveDataDelegate *delegate =
  359. [[FPRNSURLConnectionDidReceiveDataDelegate alloc] init];
  360. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  361. [connection start];
  362. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  363. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  364. GCDWebServerResponse *_Nonnull response) {
  365. XCTAssertTrue(delegate.connectionDidFinishLoadingCalled);
  366. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  367. }];
  368. [instrument deregisterInstrumentors];
  369. }
  370. /** Tests calling -connection:didWriteData:totalBytesWritten:expectedTotalBytes is wrapped and
  371. * calls through.
  372. */
  373. - (void)testConnectionDidWriteDataTotalBytesWrittenExpectedTotalBytes {
  374. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  375. [instrument registerInstrumentors];
  376. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testUpload"];
  377. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
  378. request.HTTPMethod = @"POST";
  379. FPRNSURLConnectionCompleteTestDelegate *delegate =
  380. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  381. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  382. [connection start];
  383. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  384. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  385. GCDWebServerResponse *_Nonnull response) {
  386. XCTAssertTrue(delegate.connectionDidWriteDataTotalBytesWrittenExpectedTotalBytesCalled);
  387. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  388. }];
  389. [instrument deregisterInstrumentors];
  390. }
  391. /** Tests calling -connectionDidFinishDownloading:destinationURL: is wrapped and calls through.
  392. */
  393. - (void)testConnectionDidFinishDownloadingDestinationURL {
  394. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  395. [instrument registerInstrumentors];
  396. dispatch_queue_t queue = dispatch_queue_create([NSStringFromSelector(_cmd) UTF8String], 0);
  397. dispatch_async(queue, ^{
  398. });
  399. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testDownload"];
  400. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  401. FPRNSURLConnectionCompleteTestDelegate *delegate =
  402. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  403. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  404. [connection start];
  405. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  406. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  407. GCDWebServerResponse *_Nonnull response) {
  408. XCTAssertTrue(delegate.connectionDidFinishDownloadingDestinationURLCalled);
  409. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  410. }];
  411. [instrument deregisterInstrumentors];
  412. }
  413. /** Tests NSURLDownloadDelegate completion methods gets called even after SDK swizzles that
  414. * APIs.
  415. */
  416. - (void)testDownloadDelegateCompletionAPIGetsCalled {
  417. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  418. [instrument registerInstrumentors];
  419. NSURLRequest *request = [NSURLRequest requestWithURL:self.testServer.serverURL];
  420. FPRNSURLConnectionDownloadTestDelegate *delegate =
  421. [[FPRNSURLConnectionDownloadTestDelegate alloc] init];
  422. XCTAssertFalse([delegate respondsToSelector:@selector(connectionDidFinishLoading:)]);
  423. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  424. [connection start];
  425. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  426. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  427. GCDWebServerResponse *_Nonnull response) {
  428. XCTAssertTrue(delegate.connectionDidFinishDownloadingDestinationURLCalled);
  429. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  430. }];
  431. [instrument deregisterInstrumentors];
  432. }
  433. /** Tests NSURLDataDelegate completion handler gets called even after SDK swizzles that APIs.
  434. */
  435. - (void)testDataDelegateCompletionAPIGetsCalled {
  436. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  437. [instrument registerInstrumentors];
  438. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testDownload"];
  439. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  440. FPRNSURLConnectionDataTestDelegate *delegate = [[FPRNSURLConnectionDataTestDelegate alloc] init];
  441. SEL selector = @selector(connectionDidFinishDownloading:destinationURL:);
  442. XCTAssertFalse([delegate respondsToSelector:selector]);
  443. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  444. [connection start];
  445. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  446. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  447. GCDWebServerResponse *_Nonnull response) {
  448. XCTAssertTrue(delegate.connectionDidFinishLoadingCalled);
  449. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  450. }];
  451. [instrument deregisterInstrumentors];
  452. }
  453. /** Tests NSURLDownloadDelegate completion methods gets called even if NSURLDataDelegate is
  454. * implemented.
  455. */
  456. - (void)testDownloadDelegateCompletionAPIGetsCalledEvenIfDataDelegateIsImplemented {
  457. FPRNSURLConnectionInstrument *instrument = [[FPRNSURLConnectionInstrument alloc] init];
  458. [instrument registerInstrumentors];
  459. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testDownload"];
  460. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  461. FPRNSURLConnectionCompleteTestDelegate *delegate =
  462. [[FPRNSURLConnectionCompleteTestDelegate alloc] init];
  463. SEL selector = @selector(connectionDidFinishDownloading:destinationURL:);
  464. XCTAssertTrue([delegate respondsToSelector:selector]);
  465. XCTAssertTrue([delegate respondsToSelector:@selector(connectionDidFinishLoading:)]);
  466. NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:delegate];
  467. [connection start];
  468. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:connection]);
  469. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  470. GCDWebServerResponse *_Nonnull response) {
  471. XCTAssertTrue(delegate.connectionDidFinishDownloadingDestinationURLCalled);
  472. XCTAssertFalse(delegate.connectionDidFinishLoadingCalled);
  473. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:connection]);
  474. }];
  475. [instrument deregisterInstrumentors];
  476. }
  477. @end