FPRNSURLConnectionInstrumentTest.m 26 KB

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