FPRNSURLSessionInstrumentTest.m 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  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. #import "FirebasePerformance/Tests/Unit/Instruments/FPRNSURLSessionInstrumentTestDelegates.h"
  16. #import <XCTest/XCTest.h>
  17. #import <objc/runtime.h>
  18. #import "FirebasePerformance/Sources/Configurations/FPRConfigurations+Private.h"
  19. #import "FirebasePerformance/Sources/Configurations/FPRConfigurations.h"
  20. #import "FirebasePerformance/Sources/Instrumentation/FPRNetworkTrace.h"
  21. #import "FirebasePerformance/Sources/Instrumentation/Network/FPRNSURLSessionInstrument.h"
  22. #import "FirebasePerformance/Sources/Instrumentation/Network/FPRNSURLSessionInstrument_Private.h"
  23. #import "FirebasePerformance/Sources/Public/FirebasePerformance/FIRPerformance.h"
  24. #import "FirebasePerformance/Tests/Unit/FPRTestCase.h"
  25. #import "FirebasePerformance/Tests/Unit/FPRTestUtils.h"
  26. #import "FirebasePerformance/Tests/Unit/Server/FPRHermeticTestServer.h"
  27. /** This class is used to wrap an NSURLSession object during testing. */
  28. @interface FPRNSURLSessionProxy : NSProxy {
  29. // The wrapped session object.
  30. id _session;
  31. }
  32. /** @return an instance of the session proxy. */
  33. - (instancetype)initWithSession:(id)session;
  34. @end
  35. @implementation FPRNSURLSessionProxy
  36. - (instancetype)initWithSession:(id)session {
  37. if (self) {
  38. _session = session;
  39. }
  40. return self;
  41. }
  42. - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
  43. return [_session methodSignatureForSelector:selector];
  44. }
  45. - (void)forwardInvocation:(NSInvocation *)invocation {
  46. [invocation invokeWithTarget:_session];
  47. }
  48. @end
  49. @interface FPRNSURLSessionInstrumentTest : FPRTestCase
  50. /** Test server to create connections to. */
  51. @property(nonatomic) FPRHermeticTestServer *testServer;
  52. @end
  53. @implementation FPRNSURLSessionInstrumentTest
  54. - (void)setUp {
  55. [super setUp];
  56. FIRPerformance *performance = [FIRPerformance sharedInstance];
  57. [performance setDataCollectionEnabled:YES];
  58. XCTAssertFalse(self.testServer.isRunning);
  59. self.testServer = [[FPRHermeticTestServer alloc] init];
  60. [self.testServer registerTestPaths];
  61. [self.testServer start];
  62. }
  63. - (void)tearDown {
  64. [super tearDown];
  65. FIRPerformance *performance = [FIRPerformance sharedInstance];
  66. [performance setDataCollectionEnabled:NO];
  67. [self.testServer stop];
  68. [FPRConfigurations reset];
  69. }
  70. /** Waits for the server connection to finish by giving a block to run just before a response is
  71. * sent.
  72. *
  73. * @param block A block to run just after the server response is sent.
  74. */
  75. - (void)waitAndRunBlockAfterResponse:(void (^)(id self,
  76. GCDWebServerRequest *_Nonnull request,
  77. GCDWebServerResponse *_Nonnull response))block {
  78. __block BOOL loopingMainThread = YES;
  79. dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
  80. dispatch_semaphore_t sema = dispatch_semaphore_create(0);
  81. __weak id weakSelf = self;
  82. self.testServer.responseCompletedBlock =
  83. ^(GCDWebServerRequest *_Nonnull request, GCDWebServerResponse *_Nonnull response) {
  84. block(weakSelf, request, response);
  85. dispatch_semaphore_signal(sema);
  86. };
  87. XCTAssertEqual(
  88. dispatch_semaphore_wait(sema, dispatch_time(DISPATCH_TIME_NOW, 10 * NSEC_PER_SEC)), 0);
  89. loopingMainThread = NO;
  90. });
  91. // This is necessary because the FPRHermeticTestServer callbacks occur on the main thread.
  92. while (loopingMainThread) {
  93. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
  94. }
  95. }
  96. #pragma mark - Testing infrastructure and subclass instrumenting
  97. /** Tests initing of FPRNSURLSessionInstrument also inits NSURLSessionDelegate instrument. */
  98. - (void)testInit {
  99. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  100. [instrument registerInstrumentors];
  101. self.testServer.responseCompletedBlock =
  102. ^(GCDWebServerRequest *_Nonnull request, GCDWebServerResponse *_Nonnull response) {
  103. XCTAssert(instrument);
  104. XCTAssert(instrument.delegateInstrument);
  105. };
  106. [instrument deregisterInstrumentors];
  107. }
  108. /** Tests that creating a shared session returns a non-nil object. */
  109. - (void)testSharedSession {
  110. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  111. [instrument registerInstrumentors];
  112. NSURLSession *session = [NSURLSession sharedSession];
  113. XCTAssertNotNil(session);
  114. [instrument deregisterInstrumentors];
  115. }
  116. /** Tests that a method that returns an NSURLSession subclass registers that subclass. */
  117. - (void)testSubclassRegistration {
  118. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  119. [instrument registerInstrumentors];
  120. NSURLSession *session = [NSURLSession sharedSession];
  121. XCTAssertNotNil(session);
  122. XCTAssertEqual(instrument.classInstrumentors.count, 2);
  123. [instrument deregisterInstrumentors];
  124. }
  125. /** Tests that a discovered subclass isn't registered more than once. */
  126. - (void)testSubclassIsNotRegisteredMoreThanOnce {
  127. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  128. [instrument registerInstrumentors];
  129. NSURLSession *session = [NSURLSession sharedSession];
  130. NSURLSession *session2 = [NSURLSession sharedSession];
  131. XCTAssertNotNil(session);
  132. XCTAssertNotNil(session2);
  133. XCTAssertEqual(instrument.classInstrumentors.count, 2);
  134. [instrument deregisterInstrumentors];
  135. }
  136. /** Tests sessionWithConfiguration: with the default configuration returns a non-nil object. */
  137. - (void)testSessionWithDefaultSessionConfiguration {
  138. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  139. [instrument registerInstrumentors];
  140. NSURLSessionConfiguration *configuration =
  141. [NSURLSessionConfiguration defaultSessionConfiguration];
  142. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
  143. XCTAssertNotNil(session);
  144. XCTAssertEqual(instrument.classInstrumentors.count, 2);
  145. [instrument deregisterInstrumentors];
  146. }
  147. /** Tests sessionWithConfiguration: with an ephemeral configuration returns a non-nil object. */
  148. - (void)testSessionWithEphemeralSessionConfiguration {
  149. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  150. [instrument registerInstrumentors];
  151. NSURLSessionConfiguration *configuration =
  152. [NSURLSessionConfiguration ephemeralSessionConfiguration];
  153. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
  154. XCTAssertNotNil(session);
  155. XCTAssertEqual(instrument.classInstrumentors.count, 2);
  156. [instrument deregisterInstrumentors];
  157. }
  158. /** Tests sessionWithConfiguration: with a background configuration returns a non-nil object. */
  159. - (void)testSessionWithBackgroundSessionConfiguration {
  160. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  161. [instrument registerInstrumentors];
  162. NSURLSessionConfiguration *configuration =
  163. [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"madeUpID"];
  164. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
  165. XCTAssertNotNil(session);
  166. XCTAssertEqual(instrument.classInstrumentors.count, 2);
  167. [instrument deregisterInstrumentors];
  168. }
  169. /** Tests instrumenting an NSProxy wrapped NSURLSession object works. */
  170. - (void)testProxyWrappedSharedSession {
  171. Method method = class_getClassMethod([NSURLSession class], @selector(sharedSession));
  172. IMP originalImp = method_getImplementation(method);
  173. IMP swizzledImp = imp_implementationWithBlock(^(id session) {
  174. typedef NSURLSession *(*OriginalImp)(id, SEL);
  175. NSURLSession *originalSession = ((OriginalImp)originalImp)(session, @selector(sharedSession));
  176. return [[FPRNSURLSessionProxy alloc] initWithSession:originalSession];
  177. });
  178. method_setImplementation(method, swizzledImp);
  179. XCTAssertEqual([[NSURLSession sharedSession] class], [FPRNSURLSessionProxy class]);
  180. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  181. [instrument registerInstrumentors];
  182. NSURLSession *session;
  183. XCTAssertNoThrow(session = [NSURLSession sharedSession]);
  184. NSURL *url = self.testServer.serverURL;
  185. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler"];
  186. NSURLSessionDownloadTask *task =
  187. [session downloadTaskWithURL:url
  188. completionHandler:^(NSURL *_Nullable location, NSURLResponse *_Nullable response,
  189. NSError *_Nullable error) {
  190. [expectation fulfill];
  191. }];
  192. [task resume];
  193. XCTAssertNotNil(task);
  194. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  195. [instrument deregisterInstrumentors];
  196. method_setImplementation(method, originalImp);
  197. XCTAssertNotEqual([[NSURLSession sharedSession] class], [FPRNSURLSessionProxy class]);
  198. }
  199. /** Tests instrumenting an NSProxy wrapped NSURLSession object works. */
  200. - (void)testProxyWrappedSessionWithConfiguration {
  201. Method method = class_getClassMethod([NSURLSession class], @selector(sessionWithConfiguration:));
  202. IMP originalImp = method_getImplementation(method);
  203. IMP swizzledImp =
  204. imp_implementationWithBlock(^(id session, NSURLSessionConfiguration *configuration) {
  205. typedef NSURLSession *(*OriginalImp)(id, SEL, NSURLSessionConfiguration *);
  206. NSURLSession *originalSession = ((OriginalImp)originalImp)(
  207. session, @selector(sessionWithConfiguration:), configuration);
  208. return [[FPRNSURLSessionProxy alloc] initWithSession:originalSession];
  209. });
  210. method_setImplementation(method, swizzledImp);
  211. NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
  212. XCTAssertEqual([[NSURLSession sessionWithConfiguration:config] class],
  213. [FPRNSURLSessionProxy class]);
  214. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  215. [instrument registerInstrumentors];
  216. NSURLSession *session;
  217. XCTAssertNoThrow(session = [NSURLSession sessionWithConfiguration:config]);
  218. NSURL *url = self.testServer.serverURL;
  219. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler"];
  220. NSURLSessionDownloadTask *task =
  221. [session downloadTaskWithURL:url
  222. completionHandler:^(NSURL *_Nullable location, NSURLResponse *_Nullable response,
  223. NSError *_Nullable error) {
  224. [expectation fulfill];
  225. }];
  226. XCTAssertNotNil(task);
  227. [task resume];
  228. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  229. [instrument deregisterInstrumentors];
  230. method_setImplementation(method, originalImp);
  231. XCTAssertNotEqual([[NSURLSession sharedSession] class], [FPRNSURLSessionProxy class]);
  232. }
  233. /** Tests instrumenting an NSProxy wrapped NSURLSession object works. */
  234. - (void)testProxyWrappedSessionWithConfigurationDelegateDelegateQueue {
  235. SEL selector = @selector(sessionWithConfiguration:delegate:delegateQueue:);
  236. Method method = class_getClassMethod([NSURLSession class], selector);
  237. IMP originalImp = method_getImplementation(method);
  238. IMP swizzledImp = imp_implementationWithBlock(
  239. ^(id session, NSURLSessionConfiguration *configuration, id<NSURLSessionDelegate> *delegate,
  240. NSOperationQueue *delegateQueue) {
  241. typedef NSURLSession *(*OriginalImp)(id, SEL, NSURLSessionConfiguration *,
  242. id<NSURLSessionDelegate> *, NSOperationQueue *);
  243. NSURLSession *originalSession =
  244. ((OriginalImp)originalImp)(session, selector, configuration, delegate, delegateQueue);
  245. return [[FPRNSURLSessionProxy alloc] initWithSession:originalSession];
  246. });
  247. method_setImplementation(method, swizzledImp);
  248. NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
  249. XCTAssertEqual([[NSURLSession sessionWithConfiguration:config delegate:nil
  250. delegateQueue:nil] class],
  251. [FPRNSURLSessionProxy class]);
  252. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  253. [instrument registerInstrumentors];
  254. NSURLSession *session;
  255. XCTAssertNoThrow(session = [NSURLSession sessionWithConfiguration:config
  256. delegate:nil
  257. delegateQueue:nil]);
  258. NSURL *url = self.testServer.serverURL;
  259. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler"];
  260. NSURLSessionDownloadTask *task =
  261. [session downloadTaskWithURL:url
  262. completionHandler:^(NSURL *_Nullable location, NSURLResponse *_Nullable response,
  263. NSError *_Nullable error) {
  264. [expectation fulfill];
  265. }];
  266. XCTAssertNotNil(task);
  267. [task resume];
  268. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  269. [instrument deregisterInstrumentors];
  270. method_setImplementation(method, originalImp);
  271. }
  272. #pragma mark - Testing delegate method wrapping
  273. /** Tests using a nil delegate still results in tracking responses. */
  274. - (void)testSessionWithConfigurationDelegateDelegateQueueWithNilDelegate {
  275. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  276. [instrument registerInstrumentors];
  277. NSURLSessionConfiguration *configuration =
  278. [NSURLSessionConfiguration defaultSessionConfiguration];
  279. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
  280. delegate:nil
  281. delegateQueue:nil];
  282. NSURLRequest *request = [NSURLRequest requestWithURL:self.testServer.serverURL];
  283. NSURLSessionTask *task;
  284. @autoreleasepool {
  285. task = [session dataTaskWithRequest:request];
  286. XCTAssertNotNil(task);
  287. [task resume];
  288. XCTAssertNotNil(session.delegate); // Not sure this is the desired behavior.
  289. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:task]);
  290. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  291. GCDWebServerResponse *_Nonnull response) {
  292. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:task]);
  293. }];
  294. }
  295. [instrument deregisterInstrumentors];
  296. }
  297. /** Tests that the delegate class isn't instrumented more than once. */
  298. - (void)testDelegateClassOnlyRegisteredOnce {
  299. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  300. [instrument registerInstrumentors];
  301. FPRNSURLSessionCompleteTestDelegate *delegate =
  302. [[FPRNSURLSessionCompleteTestDelegate alloc] init];
  303. NSURLSessionConfiguration *configuration =
  304. [NSURLSessionConfiguration defaultSessionConfiguration];
  305. [NSURLSession sessionWithConfiguration:configuration delegate:delegate delegateQueue:nil];
  306. [NSURLSession sessionWithConfiguration:configuration delegate:delegate delegateQueue:nil];
  307. XCTAssertEqual(instrument.delegateInstrument.classInstrumentors.count, 1);
  308. XCTAssertEqual(instrument.delegateInstrument.instrumentedClasses.count, 1);
  309. [instrument deregisterInstrumentors];
  310. }
  311. /** Tests that the called delegate selector is wrapped and calls through. */
  312. - (void)testDelegateURLSessionTaskDidCompleteWithError {
  313. [self.testServer stop];
  314. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  315. [instrument registerInstrumentors];
  316. FPRNSURLSessionCompleteTestDelegate *delegate =
  317. [[FPRNSURLSessionCompleteTestDelegate alloc] init];
  318. // This request needs to fail.
  319. NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://nonurl"]];
  320. NSURLSessionConfiguration *configuration =
  321. [NSURLSessionConfiguration defaultSessionConfiguration];
  322. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
  323. delegate:delegate
  324. delegateQueue:nil];
  325. NSURLSessionTask *task;
  326. @autoreleasepool {
  327. task = [session dataTaskWithRequest:request];
  328. [task resume];
  329. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:task]);
  330. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.0]];
  331. }
  332. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:task]);
  333. XCTAssertTrue(delegate.URLSessionTaskDidCompleteWithErrorCalled);
  334. [instrument deregisterInstrumentors];
  335. [self.testServer start];
  336. }
  337. /** Tests that the called delegate selector is wrapped and calls through. */
  338. - (void)testDelegateURLSessionTaskDidSendBodyDataTotalBytesSentTotalBytesExpectedToSend {
  339. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  340. [instrument registerInstrumentors];
  341. FPRNSURLSessionCompleteTestDelegate *delegate =
  342. [[FPRNSURLSessionCompleteTestDelegate alloc] init];
  343. NSURLSessionConfiguration *configuration =
  344. [NSURLSessionConfiguration defaultSessionConfiguration];
  345. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
  346. delegate:delegate
  347. delegateQueue:nil];
  348. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testUpload"];
  349. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
  350. request.HTTPMethod = @"POST";
  351. NSBundle *bundle = [FPRTestUtils getBundle];
  352. NSURL *fileURL = [bundle URLForResource:@"smallDownloadFile" withExtension:@""];
  353. NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:fileURL];
  354. [uploadTask resume];
  355. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:uploadTask]);
  356. FPRNetworkTrace *networkTrace = [FPRNetworkTrace networkTraceFromObject:uploadTask];
  357. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  358. GCDWebServerResponse *_Nonnull response) {
  359. XCTAssertTrue(delegate.URLSessionTaskDidSendBodyDataTotalBytesSentTotalBytesExpectedCalled);
  360. XCTAssert(networkTrace.requestSize > 0);
  361. XCTAssert(
  362. [networkTrace
  363. timeIntervalBetweenCheckpointState:FPRNetworkTraceCheckpointStateInitiated
  364. andState:FPRNetworkTraceCheckpointStateRequestCompleted] > 0);
  365. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:uploadTask]);
  366. }];
  367. [instrument deregisterInstrumentors];
  368. }
  369. /** Tests that the called delegate selector is wrapped and calls through. */
  370. - (void)testDelegateURLSessionTaskWillPerformHTTPRedirectionNewRequestCompletionHandler {
  371. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  372. [instrument registerInstrumentors];
  373. FPRNSURLSessionCompleteTestDelegate *delegate =
  374. [[FPRNSURLSessionCompleteTestDelegate alloc] init];
  375. NSURLSessionConfiguration *configuration =
  376. [NSURLSessionConfiguration defaultSessionConfiguration];
  377. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testRedirect"];
  378. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  379. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
  380. delegate:delegate
  381. delegateQueue:nil];
  382. NSURLSessionTask *task = [session dataTaskWithRequest:request];
  383. [task resume];
  384. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:task]);
  385. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  386. GCDWebServerResponse *_Nonnull response) {
  387. XCTAssertTrue(
  388. delegate.URLSessionTaskWillPerformHTTPRedirectionNewRequestCompletionHandlerCalled);
  389. }];
  390. [instrument deregisterInstrumentors];
  391. }
  392. /** Tests that the called delegate selector is wrapped and calls through. */
  393. - (void)testDelegateURLSessionDataTaskDidReceiveData {
  394. FPRNSURLSessionInstrument *instrument;
  395. NSURLSessionDataTask *dataTask;
  396. @autoreleasepool {
  397. instrument = [[FPRNSURLSessionInstrument alloc] init];
  398. [instrument registerInstrumentors];
  399. FPRNSURLSessionCompleteTestDelegate *delegate =
  400. [[FPRNSURLSessionCompleteTestDelegate alloc] init];
  401. NSURLSessionConfiguration *configuration =
  402. [NSURLSessionConfiguration defaultSessionConfiguration];
  403. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
  404. delegate:delegate
  405. delegateQueue:nil];
  406. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testBigDownload"];
  407. dataTask = [session dataTaskWithURL:URL];
  408. [dataTask resume];
  409. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:dataTask]);
  410. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  411. GCDWebServerResponse *_Nonnull response) {
  412. XCTAssertTrue(delegate.URLSessionDataTaskDidReceiveDataCalled);
  413. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:dataTask]);
  414. }];
  415. }
  416. [instrument deregisterInstrumentors];
  417. }
  418. /** Tests that the called delegate selector is wrapped and calls through. */
  419. - (void)testDelegateURLSessionDownloadTaskDidFinishDownloadingToURL {
  420. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  421. [instrument registerInstrumentors];
  422. FPRNSURLSessionCompleteTestDelegate *delegate =
  423. [[FPRNSURLSessionCompleteTestDelegate alloc] init];
  424. NSURLSessionConfiguration *configuration =
  425. [NSURLSessionConfiguration defaultSessionConfiguration];
  426. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
  427. delegate:delegate
  428. delegateQueue:nil];
  429. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testDownload"];
  430. NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:URL];
  431. [downloadTask resume];
  432. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  433. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  434. GCDWebServerResponse *_Nonnull response) {
  435. XCTAssertTrue(delegate.URLSessionDownloadTaskDidFinishDownloadingToURLCalled);
  436. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  437. }];
  438. [instrument deregisterInstrumentors];
  439. }
  440. /** Tests that the called delegate selector is wrapped and calls through. */
  441. - (void)testDelegateURLSessionDownloadTaskDidResumeAtOffsetExpectedTotalBytes {
  442. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  443. [instrument registerInstrumentors];
  444. FPRNSURLSessionTestDownloadDelegate *delegate =
  445. [[FPRNSURLSessionTestDownloadDelegate alloc] init];
  446. NSURLSessionConfiguration *configuration =
  447. [NSURLSessionConfiguration defaultSessionConfiguration];
  448. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
  449. delegate:delegate
  450. delegateQueue:nil];
  451. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testBigDownload"];
  452. NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:URL];
  453. [downloadTask resume];
  454. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.0]];
  455. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  456. XCTAssertTrue(delegate.URLSessionDownloadTaskDidResumeAtOffsetExpectedTotalBytesCalled);
  457. [instrument deregisterInstrumentors];
  458. }
  459. /** Tests that the called delegate selector is wrapped and calls through. */
  460. - (void)testDelegateURLSessionDownloadTaskDidWriteDataTotalBytesWrittenTotalBytesExpectedToWrite {
  461. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  462. [instrument registerInstrumentors];
  463. FPRNSURLSessionCompleteTestDelegate *delegate =
  464. [[FPRNSURLSessionCompleteTestDelegate alloc] init];
  465. NSURLSessionConfiguration *configuration =
  466. [NSURLSessionConfiguration defaultSessionConfiguration];
  467. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
  468. delegate:delegate
  469. delegateQueue:nil];
  470. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testBigDownload"];
  471. NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:URL];
  472. [downloadTask resume];
  473. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  474. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  475. GCDWebServerResponse *_Nonnull response) {
  476. XCTAssertTrue(delegate.URLSessionDownloadTaskDidWriteDataTotalBytesWrittenTotalBytesCalled);
  477. [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
  478. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  479. }];
  480. [instrument deregisterInstrumentors];
  481. }
  482. /** Tests that even if a delegate doesn't implement a method, we add it to the delegate class. */
  483. - (void)testDelegateUnimplementedURLSessionTaskDidCompleteWithError {
  484. FPRNSURLSessionTestDelegate *delegate = [[FPRNSURLSessionTestDelegate alloc] init];
  485. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  486. [instrument registerInstrumentors];
  487. NSURLSessionConfiguration *configuration =
  488. [NSURLSessionConfiguration defaultSessionConfiguration];
  489. XCTAssertFalse([delegate respondsToSelector:@selector(URLSession:task:didCompleteWithError:)]);
  490. NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration
  491. delegate:delegate
  492. delegateQueue:nil];
  493. XCTAssertTrue([delegate respondsToSelector:@selector(URLSession:task:didCompleteWithError:)]);
  494. NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:self.testServer.serverURL];
  495. [downloadTask resume];
  496. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  497. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  498. GCDWebServerResponse *_Nonnull response) {
  499. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  500. }];
  501. [instrument deregisterInstrumentors];
  502. }
  503. #pragma mark - Testing instance method wrapping
  504. /** Tests that dataTaskWithRequest: returns a non-nil object. */
  505. - (void)testDataTaskWithRequest {
  506. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  507. [instrument registerInstrumentors];
  508. NSURLSession *session = [NSURLSession sharedSession];
  509. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"test"];
  510. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  511. NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
  512. XCTAssertNotNil(dataTask);
  513. [dataTask resume];
  514. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:dataTask]);
  515. [instrument deregisterInstrumentors];
  516. }
  517. /** Tests that dataTaskWithRequest:completionHandler: returns a non-nil object. */
  518. - (void)testDataTaskWithRequestAndCompletionHandler {
  519. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  520. [instrument registerInstrumentors];
  521. NSURLSession *session = [NSURLSession sharedSession];
  522. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"test"];
  523. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  524. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler called"];
  525. void (^completionHandler)(NSData *_Nullable, NSURLResponse *_Nullable, NSError *_Nullable) =
  526. ^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
  527. [expectation fulfill];
  528. };
  529. NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
  530. completionHandler:completionHandler];
  531. XCTAssertNotNil(dataTask);
  532. [dataTask resume];
  533. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  534. [instrument deregisterInstrumentors];
  535. }
  536. /** Tests that dataTaskWithRequest:completionHandler: for a POST request returns a non-nil object
  537. * and collects request size. */
  538. - (void)testDataTaskWithPostRequestAndCompletionHandler {
  539. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  540. [instrument registerInstrumentors];
  541. NSURLSession *session = [NSURLSession sharedSession];
  542. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"test"];
  543. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
  544. request.HTTPMethod = @"POST";
  545. request.HTTPBody = [@"sampleData" dataUsingEncoding:NSUTF8StringEncoding];
  546. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler called"];
  547. void (^completionHandler)(NSData *_Nullable, NSURLResponse *_Nullable, NSError *_Nullable) =
  548. ^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
  549. [expectation fulfill];
  550. };
  551. NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
  552. completionHandler:completionHandler];
  553. XCTAssertNotNil(dataTask);
  554. [dataTask resume];
  555. FPRNetworkTrace *trace = [FPRNetworkTrace networkTraceFromObject:dataTask];
  556. XCTAssertEqual(trace.requestSize, 10);
  557. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  558. [instrument deregisterInstrumentors];
  559. }
  560. /** Tests that dataTaskWithUrl:completionHandler: returns a non-nil object. */
  561. - (void)testDataTaskWithUrlAndCompletionHandler {
  562. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  563. [instrument registerInstrumentors];
  564. NSURLSession *session = [NSURLSession sharedSession];
  565. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"test"];
  566. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler called"];
  567. NSURLSessionDataTask *dataTask = nil;
  568. void (^completionHandler)(NSData *_Nullable, NSURLResponse *_Nullable, NSError *_Nullable) =
  569. ^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
  570. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:dataTask]);
  571. [expectation fulfill];
  572. };
  573. dataTask = [session dataTaskWithURL:URL completionHandler:completionHandler];
  574. XCTAssertNotNil(dataTask);
  575. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:dataTask]);
  576. [dataTask resume];
  577. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  578. [instrument deregisterInstrumentors];
  579. }
  580. /** Tests that uploadTaskWithRequest:fromFile: returns a non-nil object. */
  581. - (void)testUploadTaskWithRequestFromFile {
  582. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  583. [instrument registerInstrumentors];
  584. NSURLSession *session = [NSURLSession sharedSession];
  585. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testUpload"];
  586. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  587. NSBundle *bundle = [FPRTestUtils getBundle];
  588. NSURL *fileURL = [bundle URLForResource:@"smallDownloadFile" withExtension:@""];
  589. NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:fileURL];
  590. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:uploadTask]);
  591. XCTAssertNotNil(uploadTask);
  592. [uploadTask resume];
  593. [instrument deregisterInstrumentors];
  594. }
  595. /** Tests that uploadTaskWithRequest:fromFile:completionHandler returns a non-nil object. */
  596. - (void)testUploadTaskWithRequestFromFileCompletionHandler {
  597. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  598. [instrument registerInstrumentors];
  599. NSURLSession *session = [NSURLSession sharedSession];
  600. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testUpload"];
  601. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  602. NSBundle *bundle = [FPRTestUtils getBundle];
  603. NSURL *fileURL = [bundle URLForResource:@"smallDownloadFile" withExtension:@""];
  604. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler called"];
  605. void (^completionHandler)(NSData *_Nullable, NSURLResponse *_Nullable, NSError *_Nullable) =
  606. ^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
  607. [expectation fulfill];
  608. };
  609. NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request
  610. fromFile:fileURL
  611. completionHandler:completionHandler];
  612. XCTAssertNotNil(uploadTask);
  613. [uploadTask resume];
  614. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  615. [instrument deregisterInstrumentors];
  616. }
  617. /** Tests that uploadTaskWithRequest:fromData: returns a non-nil object. */
  618. - (void)testUploadTaskWithRequestFromData {
  619. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  620. [instrument registerInstrumentors];
  621. NSURLSession *session = [NSURLSession sharedSession];
  622. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testUpload"];
  623. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
  624. request.HTTPMethod = @"POST";
  625. NSData *data = [[NSData alloc] init];
  626. NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:data];
  627. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:uploadTask]);
  628. XCTAssertNotNil(uploadTask);
  629. [uploadTask resume];
  630. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  631. GCDWebServerResponse *_Nonnull response) {
  632. XCTAssertEqual(response.statusCode, 200);
  633. [instrument deregisterInstrumentors];
  634. }];
  635. }
  636. /** Tests that uploadTaskWithRequest:fromData:completionHandler: returns a non-nil object. */
  637. - (void)testUploadTaskWithRequestFromDataCompletionHandler {
  638. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  639. [instrument registerInstrumentors];
  640. NSURLSession *session = [NSURLSession sharedSession];
  641. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testUpload"];
  642. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  643. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler called"];
  644. void (^completionHandler)(NSData *_Nullable, NSURLResponse *_Nullable, NSError *_Nullable) =
  645. ^(NSData *_Nullable data, NSURLResponse *_Nullable response, NSError *_Nullable error) {
  646. [expectation fulfill];
  647. };
  648. NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request
  649. fromData:[[NSData alloc] init]
  650. completionHandler:completionHandler];
  651. XCTAssertNotNil(uploadTask);
  652. [uploadTask resume];
  653. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  654. [instrument deregisterInstrumentors];
  655. }
  656. /** Tests that uploadTaskWithStreamedRequest: returns a non-nil object. */
  657. - (void)testUploadTaskWithStreamedRequest {
  658. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  659. [instrument registerInstrumentors];
  660. NSURLSession *session = [NSURLSession sharedSession];
  661. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testUpload"];
  662. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  663. NSURLSessionUploadTask *uploadTask = [session uploadTaskWithStreamedRequest:request];
  664. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:uploadTask]);
  665. XCTAssertNotNil(uploadTask);
  666. [uploadTask resume];
  667. [instrument deregisterInstrumentors];
  668. }
  669. /** Tests that downloadTaskWithRequest: returns a non-nil object. */
  670. - (void)testDownloadTaskWithRequest {
  671. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  672. [instrument registerInstrumentors];
  673. NSURLSession *session = [NSURLSession sharedSession];
  674. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testDownload"];
  675. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  676. NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request];
  677. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  678. XCTAssertNotNil(downloadTask);
  679. [downloadTask resume];
  680. [instrument deregisterInstrumentors];
  681. }
  682. /** Tests that downloadTaskWithRequest:completionHandler: returns a non-nil object. */
  683. - (void)testDownloadTaskWithRequestCompletionHandler {
  684. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  685. [instrument registerInstrumentors];
  686. NSURLSession *session = [NSURLSession sharedSession];
  687. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testDownload"];
  688. NSURLRequest *request = [NSURLRequest requestWithURL:URL];
  689. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler called"];
  690. void (^completionHandler)(NSURL *_Nullable, NSURLResponse *_Nullable, NSError *_Nullable) =
  691. ^(NSURL *_Nullable location, NSURLResponse *_Nullable response, NSError *_Nullable error) {
  692. [expectation fulfill];
  693. };
  694. NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request
  695. completionHandler:completionHandler];
  696. XCTAssertNotNil(downloadTask);
  697. [downloadTask resume];
  698. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  699. [instrument deregisterInstrumentors];
  700. }
  701. /** Tests that downloadTaskWithUrl:completionHandler: returns a non-nil object. */
  702. - (void)testDownloadTaskWithURLCompletionHandler {
  703. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  704. [instrument registerInstrumentors];
  705. NSURLSession *session = [NSURLSession sharedSession];
  706. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"test"];
  707. XCTestExpectation *expectation = [self expectationWithDescription:@"completionHandler called"];
  708. NSURLSessionDownloadTask *downloadTask = nil;
  709. void (^completionHandler)(NSURL *_Nullable, NSURLResponse *_Nullable, NSError *_Nullable) =
  710. ^(NSURL *_Nullable location, NSURLResponse *_Nullable response, NSError *_Nullable error) {
  711. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  712. [expectation fulfill];
  713. };
  714. downloadTask = [session downloadTaskWithURL:URL completionHandler:completionHandler];
  715. XCTAssertNotNil(downloadTask);
  716. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  717. [downloadTask resume];
  718. [self waitForExpectationsWithTimeout:10.0 handler:nil];
  719. [instrument deregisterInstrumentors];
  720. }
  721. /** Validate that it works with NSMutableURLRequest URLs across data, upload, and download. */
  722. - (void)testMutableRequestURLs {
  723. FPRNSURLSessionInstrument *instrument = [[FPRNSURLSessionInstrument alloc] init];
  724. [instrument registerInstrumentors];
  725. NSURL *URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testDownload"];
  726. NSMutableURLRequest *URLRequest = [NSMutableURLRequest requestWithURL:URL];
  727. NSURLSession *session = [NSURLSession
  728. sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
  729. NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:URLRequest];
  730. [dataTask resume];
  731. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:dataTask]);
  732. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  733. GCDWebServerResponse *_Nonnull response) {
  734. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:dataTask]);
  735. }];
  736. NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:URLRequest];
  737. [downloadTask resume];
  738. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  739. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  740. GCDWebServerResponse *_Nonnull response) {
  741. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:downloadTask]);
  742. }];
  743. URL = [self.testServer.serverURL URLByAppendingPathComponent:@"testUpload"];
  744. URLRequest.URL = URL;
  745. URLRequest.HTTPMethod = @"POST";
  746. NSData *uploadData = [[NSData alloc] init];
  747. NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:URLRequest
  748. fromData:uploadData];
  749. [uploadTask resume];
  750. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:uploadTask]);
  751. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  752. GCDWebServerResponse *_Nonnull response) {
  753. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:uploadTask]);
  754. }];
  755. NSBundle *bundle = [FPRTestUtils getBundle];
  756. NSURL *fileURL = [bundle URLForResource:@"smallDownloadFile" withExtension:@""];
  757. uploadTask = [session uploadTaskWithRequest:URLRequest fromFile:fileURL];
  758. [uploadTask resume];
  759. XCTAssertNotNil([FPRNetworkTrace networkTraceFromObject:uploadTask]);
  760. [self waitAndRunBlockAfterResponse:^(id self, GCDWebServerRequest *_Nonnull request,
  761. GCDWebServerResponse *_Nonnull response) {
  762. XCTAssertNil([FPRNetworkTrace networkTraceFromObject:uploadTask]);
  763. }];
  764. [instrument deregisterInstrumentors];
  765. }
  766. @end