From b1c82a0eb8d76be317a568c445981223a39749dd Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko Date: Thu, 20 Aug 2015 21:00:55 -0700 Subject: [PATCH 1/2] Add notifications on every network request sent. --- .../CommandRunner/PFCommandRunningConstants.h | 24 +++++++++++ .../CommandRunner/PFCommandRunningConstants.m | 9 ++++ .../URLSession/PFURLSessionCommandRunner.m | 41 +++++++++++++++++-- .../PFURLSessionCommandRunner_Private.h | 3 +- .../URLSession/Session/PFURLSession.h | 19 +++++++-- .../URLSession/Session/PFURLSession.m | 24 +++++++---- .../URLSession/Session/PFURLSession_Private.h | 6 ++- .../PFURLSessionDataTaskDelegate.h | 2 + .../PFURLSessionDataTaskDelegate_Private.h | 2 - Tests/Unit/URLSessionCommandRunnerTests.m | 20 ++++++--- 10 files changed, 127 insertions(+), 23 deletions(-) diff --git a/Parse/Internal/Commands/CommandRunner/PFCommandRunningConstants.h b/Parse/Internal/Commands/CommandRunner/PFCommandRunningConstants.h index 7531fde0a..21c2706da 100644 --- a/Parse/Internal/Commands/CommandRunner/PFCommandRunningConstants.h +++ b/Parse/Internal/Commands/CommandRunner/PFCommandRunningConstants.h @@ -33,3 +33,27 @@ extern NSString *const PFCommandHeaderNameSessionToken; ///-------------------------------------- extern NSString *const PFCommandParameterNameMethodOverride; + +///-------------------------------------- +/// @name Notifications +///-------------------------------------- + +/*! + @abstract The name of the notification that is going to be sent before any URL request is sent. + */ +extern NSString *const PFCommandRunnerWillSendURLRequestNotification; + +/*! + @abstract The name of the notification that is going to be sent after any URL response is received. + */ +extern NSString *const PFCommandRunnerDidReceiveURLResponseNotification; + +/*! + @abstract The key of request(NSURLRequest) in the userInfo dictionary of a notification. + */ +extern NSString *const PFCommandRunnerNotificationURLRequestUserInfoKey; + +/*! + @abstract The key of response(NSHTTPURLResponse) in the userInfo dictionary of a notification. + */ +extern NSString *const PFCommandRunnerNotificationURLResponseUserInfoKey; diff --git a/Parse/Internal/Commands/CommandRunner/PFCommandRunningConstants.m b/Parse/Internal/Commands/CommandRunner/PFCommandRunningConstants.m index 3ea747f49..d8c37a1c0 100644 --- a/Parse/Internal/Commands/CommandRunner/PFCommandRunningConstants.m +++ b/Parse/Internal/Commands/CommandRunner/PFCommandRunningConstants.m @@ -21,3 +21,12 @@ NSString *const PFCommandHeaderNameSessionToken = @"X-Parse-Session-Token"; NSString *const PFCommandParameterNameMethodOverride = @"_method"; + +///-------------------------------------- +#pragma mark - Notifications +///-------------------------------------- + +NSString *const PFCommandRunnerWillSendURLRequestNotification = @"PFCommandRunnerWillSendURLRequestNotification"; +NSString *const PFCommandRunnerDidReceiveURLResponseNotification = @"PFCommandRunnerDidReceiveURLResponseNotification"; +NSString *const PFCommandRunnerNotificationURLRequestUserInfoKey = @"PFCommandRunnerNotificationURLRequestUserInfoKey"; +NSString *const PFCommandRunnerNotificationURLResponseUserInfoKey = @"PFCommandRunnerNotificationURLResponseUserInfoKey"; diff --git a/Parse/Internal/Commands/CommandRunner/URLSession/PFURLSessionCommandRunner.m b/Parse/Internal/Commands/CommandRunner/URLSession/PFURLSessionCommandRunner.m index 32ce9022e..021ace80f 100644 --- a/Parse/Internal/Commands/CommandRunner/URLSession/PFURLSessionCommandRunner.m +++ b/Parse/Internal/Commands/CommandRunner/URLSession/PFURLSessionCommandRunner.m @@ -30,6 +30,12 @@ #import "PFURLConstructor.h" #import "PFURLSession.h" +@interface PFURLSessionCommandRunner () + +@property (nonatomic, strong) NSNotificationCenter *notificationCenter; + +@end + @implementation PFURLSessionCommandRunner @synthesize applicationId = _applicationId; @@ -49,11 +55,12 @@ - (instancetype)initWithDataSource:(id)da clientKey:(NSString *)clientKey { NSURLSessionConfiguration *configuration = [[self class] _urlSessionConfigurationForApplicationId:applicationId clientKey:clientKey]; - PFURLSession *session = [PFURLSession sessionWithConfiguration:configuration]; + PFURLSession *session = [PFURLSession sessionWithConfiguration:configuration delegate:self]; PFCommandURLRequestConstructor *constructor = [PFCommandURLRequestConstructor constructorWithDataSource:dataSource]; self = [self initWithDataSource:dataSource session:session - requestConstructor:constructor]; + requestConstructor:constructor + notificationCenter:[NSNotificationCenter defaultCenter]]; if (!self) return nil; _applicationId = [applicationId copy]; @@ -64,7 +71,8 @@ - (instancetype)initWithDataSource:(id)da - (instancetype)initWithDataSource:(id)dataSource session:(PFURLSession *)session - requestConstructor:(PFCommandURLRequestConstructor *)requestConstructor { + requestConstructor:(PFCommandURLRequestConstructor *)requestConstructor + notificationCenter:(NSNotificationCenter *)notificationCenter { self = [super init]; if (!self) return nil; @@ -72,6 +80,7 @@ - (instancetype)initWithDataSource:(id)da _requestConstructor = requestConstructor; _session = session; + _notificationCenter = notificationCenter; return self; } @@ -237,4 +246,30 @@ + (NSURLSessionConfiguration *)_urlSessionConfigurationForApplicationId:(NSStrin return configuration; } +///-------------------------------------- +#pragma mark - PFURLSessionDelegate +///-------------------------------------- + +- (void)urlSession:(PFURLSession *)session willPerformURLRequest:(NSURLRequest *)request { + [[BFExecutor defaultPriorityBackgroundExecutor] execute:^{ + NSDictionary *userInfo = @{ PFCommandRunnerNotificationURLRequestUserInfoKey : request }; + [self.notificationCenter postNotificationName:PFCommandRunnerWillSendURLRequestNotification + object:self + userInfo:userInfo]; + }]; +} + +- (void)urlSession:(PFURLSession *)session didPerformURLRequest:(NSURLRequest *)request withURLResponse:(nullable NSURLResponse *)response { + [[BFExecutor defaultPriorityBackgroundExecutor] execute:^{ + NSMutableDictionary *userInfo = [NSMutableDictionary dictionary]; + userInfo[PFCommandRunnerNotificationURLRequestUserInfoKey] = request; + if (response) { + userInfo[PFCommandRunnerNotificationURLResponseUserInfoKey] = response; + } + [self.notificationCenter postNotificationName:PFCommandRunnerDidReceiveURLResponseNotification + object:self + userInfo:userInfo]; + }]; +} + @end diff --git a/Parse/Internal/Commands/CommandRunner/URLSession/PFURLSessionCommandRunner_Private.h b/Parse/Internal/Commands/CommandRunner/URLSession/PFURLSessionCommandRunner_Private.h index bca97674d..e10c6f180 100644 --- a/Parse/Internal/Commands/CommandRunner/URLSession/PFURLSessionCommandRunner_Private.h +++ b/Parse/Internal/Commands/CommandRunner/URLSession/PFURLSessionCommandRunner_Private.h @@ -21,7 +21,8 @@ NS_ASSUME_NONNULL_BEGIN - (instancetype)initWithDataSource:(id)dataSource session:(PFURLSession *)session - requestConstructor:(PFCommandURLRequestConstructor *)requestConstructor NS_DESIGNATED_INITIALIZER; + requestConstructor:(PFCommandURLRequestConstructor *)requestConstructor + notificationCenter:(NSNotificationCenter *)notificationCenter NS_DESIGNATED_INITIALIZER; @end diff --git a/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession.h b/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession.h index 67196bbf8..47ee56c36 100644 --- a/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession.h +++ b/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession.h @@ -17,15 +17,29 @@ NS_ASSUME_NONNULL_BEGIN +@class PFURLSession; + +@protocol PFURLSessionDelegate + +- (void)urlSession:(PFURLSession *)session willPerformURLRequest:(NSURLRequest *)request; +- (void)urlSession:(PFURLSession *)session didPerformURLRequest:(NSURLRequest *)request withURLResponse:(nullable NSURLResponse *)response; + +@end + @interface PFURLSession : NSObject +@property (nonatomic, weak, readonly) id delegate; + ///-------------------------------------- /// @name Init ///-------------------------------------- - (instancetype)init NS_UNAVAILABLE; -- (instancetype)initWithConfiguration:(NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER; -+ (instancetype)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration; +- (instancetype)initWithConfiguration:(NSURLSessionConfiguration *)configuration + delegate:(id)delegate NS_DESIGNATED_INITIALIZER; + ++ (instancetype)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration + delegate:(id)delegate; ///-------------------------------------- /// @name Teardown @@ -52,7 +66,6 @@ NS_ASSUME_NONNULL_BEGIN withCancellationToken:(nullable BFCancellationToken *)cancellationToken progressBlock:(nullable PFProgressBlock)progressBlock; - @end NS_ASSUME_NONNULL_END diff --git a/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession.m b/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession.m index 0ac976378..b4d7b53f8 100644 --- a/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession.m +++ b/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession.m @@ -41,17 +41,21 @@ - (instancetype)init { PFNotDesignatedInitializer(); } -- (instancetype)initWithConfiguration:(NSURLSessionConfiguration *)configuration { +- (instancetype)initWithConfiguration:(NSURLSessionConfiguration *)configuration + delegate:(id)delegate { // NOTE: cast to id suppresses warning about designated initializer. return [(id)self initWithURLSession:[NSURLSession sessionWithConfiguration:configuration delegate:self - delegateQueue:nil]]; + delegateQueue:nil] + delegate:delegate]; } -- (instancetype)initWithURLSession:(NSURLSession *)session { +- (instancetype)initWithURLSession:(NSURLSession *)session + delegate:(id)delegate { self = [super init]; if (!self) return nil; + _delegate = delegate; _urlSession = session; _sessionTaskQueue = dispatch_queue_create("com.parse.urlSession.tasks", DISPATCH_QUEUE_SERIAL); @@ -62,12 +66,14 @@ - (instancetype)initWithURLSession:(NSURLSession *)session { return self; } -+ (instancetype)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration { - return [[self alloc] initWithConfiguration:configuration]; ++ (instancetype)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration + delegate:(id)delegate { + return [[self alloc] initWithConfiguration:configuration delegate:delegate]; } -+ (instancetype)sessionWithURLSession:(nonnull NSURLSession *)session { - return [[self alloc] initWithURLSession:session]; ++ (instancetype)sessionWithURLSession:(nonnull NSURLSession *)session + delegate:(id)delegate { + return [[self alloc] initWithURLSession:session delegate:delegate]; } ///-------------------------------------- @@ -161,6 +167,8 @@ - (BFTask *)performFileDownloadURLRequestAsync:(NSURLRequest *)request } - (BFTask *)_performDataTask:(NSURLSessionDataTask *)dataTask withDelegate:(PFURLSessionDataTaskDelegate *)delegate { + [self.delegate urlSession:self willPerformURLRequest:dataTask.originalRequest]; + @weakify(self); return [BFTask taskFromExecutor:[BFExecutor defaultExecutor] withBlock:^id{ @strongify(self); @@ -169,6 +177,8 @@ - (BFTask *)_performDataTask:(NSURLSessionDataTask *)dataTask withDelegate:(PFUR BFTask *resultTask = [delegate.resultTask continueWithBlock:^id(BFTask *task) { @strongify(self); + [self.delegate urlSession:self didPerformURLRequest:dataTask.originalRequest withURLResponse:delegate.response]; + [self _removeDelegateForTaskWithIdentifier:taskIdentifier]; return task; }]; diff --git a/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession_Private.h b/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession_Private.h index e7068256f..1f047acb8 100644 --- a/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession_Private.h +++ b/Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession_Private.h @@ -13,9 +13,11 @@ NS_ASSUME_NONNULL_BEGIN @interface PFURLSession () -- (instancetype)initWithURLSession:(NSURLSession *)session NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithURLSession:(NSURLSession *)session + delegate:(id)delegate NS_DESIGNATED_INITIALIZER; -+ (instancetype)sessionWithURLSession:(NSURLSession *)session; ++ (instancetype)sessionWithURLSession:(NSURLSession *)session + delegate:(id)delegate; @end diff --git a/Parse/Internal/Commands/CommandRunner/URLSession/Session/TaskDelegate/PFURLSessionDataTaskDelegate.h b/Parse/Internal/Commands/CommandRunner/URLSession/Session/TaskDelegate/PFURLSessionDataTaskDelegate.h index af9a37238..b4dd41f87 100644 --- a/Parse/Internal/Commands/CommandRunner/URLSession/Session/TaskDelegate/PFURLSessionDataTaskDelegate.h +++ b/Parse/Internal/Commands/CommandRunner/URLSession/Session/TaskDelegate/PFURLSessionDataTaskDelegate.h @@ -19,6 +19,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, readonly) NSURLSessionDataTask *dataTask; @property (nonatomic, strong, readonly) BFTask *resultTask; +@property (nonatomic, strong, readonly) NSHTTPURLResponse *response; + - (instancetype)init NS_UNAVAILABLE; - (instancetype)initForDataTask:(NSURLSessionDataTask *)dataTask withCancellationToken:(nullable BFCancellationToken *)cancellationToken NS_DESIGNATED_INITIALIZER; diff --git a/Parse/Internal/Commands/CommandRunner/URLSession/Session/TaskDelegate/PFURLSessionDataTaskDelegate_Private.h b/Parse/Internal/Commands/CommandRunner/URLSession/Session/TaskDelegate/PFURLSessionDataTaskDelegate_Private.h index bd2d1c963..1d4123122 100644 --- a/Parse/Internal/Commands/CommandRunner/URLSession/Session/TaskDelegate/PFURLSessionDataTaskDelegate_Private.h +++ b/Parse/Internal/Commands/CommandRunner/URLSession/Session/TaskDelegate/PFURLSessionDataTaskDelegate_Private.h @@ -13,8 +13,6 @@ @property (nonatomic, strong, readonly) dispatch_queue_t dataQueue; -@property (nonatomic, strong, readonly) NSHTTPURLResponse *response; - /*! @abstract Defaults to to-memory output stream if not overwritten. */ diff --git a/Tests/Unit/URLSessionCommandRunnerTests.m b/Tests/Unit/URLSessionCommandRunnerTests.m index 81349d2bd..1c61989e5 100644 --- a/Tests/Unit/URLSessionCommandRunnerTests.m +++ b/Tests/Unit/URLSessionCommandRunnerTests.m @@ -54,6 +54,7 @@ - (void)testRunCommand { id mockedDataSource = PFStrictProtocolMock(@protocol(PFInstallationIdentifierStoreProvider)); id mockedSession = PFStrictClassMock([PFURLSession class]); id mockedRequestConstructor = PFStrictClassMock([PFCommandURLRequestConstructor class]); + id mockedNotificationCenter = PFStrictClassMock([NSNotificationCenter class]); id mockedCommand = PFStrictClassMock([PFRESTCommand class]); id mockedCommandResult = PFStrictClassMock([PFCommandResult class]); @@ -71,7 +72,8 @@ - (void)testRunCommand { PFURLSessionCommandRunner *commandRunner = [[PFURLSessionCommandRunner alloc] initWithDataSource:mockedDataSource session:mockedSession - requestConstructor:mockedRequestConstructor]; + requestConstructor:mockedRequestConstructor + notificationCenter:mockedNotificationCenter]; XCTestExpectation *expecatation = [self currentSelectorTestExpectation]; [[commandRunner runCommandAsync:mockedCommand withOptions:0] continueWithBlock:^id(BFTask *task) { @@ -89,6 +91,7 @@ - (void)testRunCommandCancel { id mockedDataSource = PFStrictProtocolMock(@protocol(PFInstallationIdentifierStoreProvider)); id mockedSession = PFStrictClassMock([PFURLSession class]); id mockedRequestConstructor = PFStrictClassMock([PFCommandURLRequestConstructor class]); + id mockedNotificationCenter = PFStrictClassMock([NSNotificationCenter class]); id mockedCommand = PFStrictClassMock([PFRESTCommand class]); @@ -96,7 +99,8 @@ - (void)testRunCommandCancel { PFURLSessionCommandRunner *commandRunner = [[PFURLSessionCommandRunner alloc] initWithDataSource:mockedDataSource session:mockedSession - requestConstructor:mockedRequestConstructor]; + requestConstructor:mockedRequestConstructor + notificationCenter:mockedNotificationCenter]; BFCancellationTokenSource *cancellationToken = [BFCancellationTokenSource cancellationTokenSource]; [cancellationToken cancel]; @@ -117,6 +121,7 @@ - (void)testRunCommandRetry { id mockedDataSource = PFStrictProtocolMock(@protocol(PFInstallationIdentifierStoreProvider)); id mockedSession = PFStrictClassMock([PFURLSession class]); id mockedRequestConstructor = PFStrictClassMock([PFCommandURLRequestConstructor class]); + id mockedNotificationCenter = PFStrictClassMock([NSNotificationCenter class]); id mockedCommand = PFStrictClassMock([PFRESTCommand class]); @@ -140,7 +145,8 @@ - (void)testRunCommandRetry { PFURLSessionCommandRunner *commandRunner = [[PFURLSessionCommandRunner alloc] initWithDataSource:mockedDataSource session:mockedSession - requestConstructor:mockedRequestConstructor]; + requestConstructor:mockedRequestConstructor + notificationCenter:mockedNotificationCenter]; commandRunner.initialRetryDelay = DBL_MIN; // Lets not needlessly sleep here. XCTestExpectation *expecatation = [self currentSelectorTestExpectation]; @@ -162,6 +168,7 @@ - (void)testRunFileUpload { id mockedDataSource = PFStrictProtocolMock(@protocol(PFInstallationIdentifierStoreProvider)); id mockedSession = PFStrictClassMock([PFURLSession class]); id mockedRequestConstructor = PFStrictClassMock([PFCommandURLRequestConstructor class]); + id mockedNotificationCenter = PFStrictClassMock([NSNotificationCenter class]); id mockedCommand = PFStrictClassMock([PFRESTCommand class]); id mockedCommandResult = PFStrictClassMock([PFCommandResult class]); @@ -191,7 +198,8 @@ - (void)testRunFileUpload { PFURLSessionCommandRunner *commandRunner = [[PFURLSessionCommandRunner alloc] initWithDataSource:mockedDataSource session:mockedSession - requestConstructor:mockedRequestConstructor]; + requestConstructor:mockedRequestConstructor + notificationCenter:mockedNotificationCenter]; XCTestExpectation *expecatation = [self currentSelectorTestExpectation]; [[commandRunner runFileUploadCommandAsync:mockedCommand @@ -213,6 +221,7 @@ - (void)testLocalIdResolution { id mockedDataSource = PFStrictProtocolMock(@protocol(PFInstallationIdentifierStoreProvider)); id mockedSession = PFStrictClassMock([PFURLSession class]); id mockedRequestConstructor = PFStrictClassMock([PFCommandURLRequestConstructor class]); + id mockedNotificationCenter = PFStrictClassMock([NSNotificationCenter class]); id mockedCommand = PFStrictClassMock([PFRESTCommand class]); id mockedCommandResult = PFStrictClassMock([PFCommandResult class]); @@ -230,7 +239,8 @@ - (void)testLocalIdResolution { PFURLSessionCommandRunner *commandRunner = [[PFURLSessionCommandRunner alloc] initWithDataSource:mockedDataSource session:mockedSession - requestConstructor:mockedRequestConstructor]; + requestConstructor:mockedRequestConstructor + notificationCenter:mockedNotificationCenter]; XCTestExpectation *expecatation = [self currentSelectorTestExpectation]; [[commandRunner runCommandAsync:mockedCommand withOptions:0] continueWithBlock:^id(BFTask *task) { From b1b1abda36d6a31c60c718c1ee2c8c443509df1e Mon Sep 17 00:00:00 2001 From: Nikita Lutsenko Date: Thu, 20 Aug 2015 21:01:07 -0700 Subject: [PATCH 2/2] Update tests for PFURLSessionDelegate. --- Tests/Unit/URLSessionTests.m | 76 ++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 13 deletions(-) diff --git a/Tests/Unit/URLSessionTests.m b/Tests/Unit/URLSessionTests.m index a9e445e82..83ff3a112 100644 --- a/Tests/Unit/URLSessionTests.m +++ b/Tests/Unit/URLSessionTests.m @@ -25,6 +25,7 @@ @interface MockedSessionTask : NSObject @property (atomic, assign) NSUInteger taskIdentifier; +@property (nonatomic, strong) NSURLRequest *originalRequest; @property (nonatomic, strong) void (^resumeBlock)(); @property (nonatomic, strong) void (^cancelBlock)(); @@ -62,20 +63,29 @@ @implementation URLSessionTests - (void)testConstructors { NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *URLSession = [NSURLSession sharedSession]; + id delegate = PFStrictProtocolMock(@protocol(PFURLSessionDelegate)); - PFURLSession *session = [[PFURLSession alloc] initWithConfiguration:configuration]; + PFURLSession *session = [[PFURLSession alloc] initWithConfiguration:configuration + delegate:delegate]; XCTAssertNotNil(session); + XCTAssertEqual((id)session.delegate, delegate); [session invalidateAndCancel]; - session = [PFURLSession sessionWithConfiguration:configuration]; + session = [PFURLSession sessionWithConfiguration:configuration + delegate:delegate]; XCTAssertNotNil(session); + XCTAssertEqual((id)session.delegate, delegate); [session invalidateAndCancel]; - session = [[PFURLSession alloc] initWithURLSession:URLSession]; + session = [[PFURLSession alloc] initWithURLSession:URLSession + delegate:delegate]; XCTAssertNotNil(URLSession); + XCTAssertEqual((id)session.delegate, delegate); - session = [PFURLSession sessionWithURLSession:URLSession]; + session = [PFURLSession sessionWithURLSession:URLSession + delegate:delegate]; XCTAssertNotNil(session); + XCTAssertEqual((id)session.delegate, delegate); PFAssertThrowsInconsistencyException([PFURLSession new]); } @@ -87,6 +97,7 @@ - (void)testPerformDataRequestSuccess { NSArray *mocks = @[ mockedURLSession, mockedURLRequest, mockedCommand ]; MockedSessionTask *mockedDataTask = [[MockedSessionTask alloc] init]; + mockedDataTask.originalRequest = mockedURLRequest; __block id sessionDelegate = nil; @@ -115,9 +126,13 @@ - (void)testPerformDataRequestSuccess { [sessionDelegate URLSession:mockedURLSession task:(id)mockedDataTask didCompleteWithError:nil]; }; - PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession]; + id delegate = PFStrictProtocolMock(@protocol(PFURLSessionDelegate)); + PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession delegate:delegate]; sessionDelegate = (id)session; + OCMExpect([delegate urlSession:session willPerformURLRequest:mockedURLRequest]); + OCMExpect([delegate urlSession:session didPerformURLRequest:mockedURLRequest withURLResponse:[OCMArg isNotNil]]); + XCTestExpectation *expectation = [self currentSelectorTestExpectation]; [[session performDataURLRequestAsync:mockedURLRequest forCommand:mockedCommand cancellationToken:nil] continueWithBlock:^id(BFTask *task) { PFCommandResult *actualResult = task.result; @@ -128,6 +143,7 @@ - (void)testPerformDataRequestSuccess { [self waitForTestExpectations]; OCMVerifyAll((id)mockedURLSession); + OCMVerifyAll(delegate); [mocks makeObjectsPerformSelector:@selector(stopMocking)]; } @@ -135,10 +151,11 @@ - (void)testPerformDataRequesPreCancel { NSURLSession *mockedURLSession = PFStrictClassMock([NSURLSession class]); NSURLRequest *mockedURLRequest = PFStrictClassMock([NSURLRequest class]); PFRESTCommand *mockedCommand = PFStrictClassMock([PFRESTCommand class]); + id delegate = PFStrictProtocolMock(@protocol(PFURLSessionDelegate)); NSArray *mocks = @[ mockedURLSession, mockedURLRequest, mockedCommand ]; BFCancellationTokenSource *cancellationTokenSource = [BFCancellationTokenSource cancellationTokenSource]; - PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession]; + PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession delegate:delegate]; XCTestExpectation *expectation = [self currentSelectorTestExpectation]; @@ -162,6 +179,7 @@ - (void)testPerformDataRequestCancellation { NSArray *mocks = @[ mockedURLSession, mockedURLRequest, mockedCommand ]; MockedSessionTask *mockedDataTask = [[MockedSessionTask alloc] init]; + mockedDataTask.originalRequest = mockedURLRequest; BFCancellationTokenSource *cancellationTokenSource = [BFCancellationTokenSource cancellationTokenSource]; __block id sessionDelegate = nil; @@ -199,9 +217,13 @@ - (void)testPerformDataRequestCancellation { [cancelExpectation fulfill]; }; - PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession]; + id delegate = PFStrictProtocolMock(@protocol(PFURLSessionDelegate)); + PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession delegate:delegate]; sessionDelegate = (id)session; + OCMExpect([delegate urlSession:session willPerformURLRequest:mockedURLRequest]); + OCMExpect([delegate urlSession:session didPerformURLRequest:mockedURLRequest withURLResponse:[OCMArg isNotNil]]); + XCTestExpectation *expectation = [self currentSelectorTestExpectation]; [[session performDataURLRequestAsync:mockedURLRequest forCommand:mockedCommand @@ -213,6 +235,7 @@ - (void)testPerformDataRequestCancellation { [self waitForTestExpectations]; OCMVerifyAll((id)mockedURLSession); + OCMVerifyAll(delegate); [mocks makeObjectsPerformSelector:@selector(stopMocking)]; } @@ -223,6 +246,7 @@ - (void)testPerformDataRequestError { NSArray *mocks = @[ mockedURLSession, mockedURLRequest, mockedCommand ]; MockedSessionTask *mockedDataTask = [[MockedSessionTask alloc] init]; + mockedDataTask.originalRequest = mockedURLRequest; NSError *expectedError = [NSError errorWithDomain:PFParseErrorDomain code:1337 userInfo:nil]; __block id sessionDelegate = nil; @@ -237,9 +261,13 @@ - (void)testPerformDataRequestError { [sessionDelegate URLSession:mockedURLSession task:(id)mockedDataTask didCompleteWithError:expectedError]; }; - PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession]; + id delegate = PFStrictProtocolMock(@protocol(PFURLSessionDelegate)); + PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession delegate:delegate]; sessionDelegate = (id)session; + OCMExpect([delegate urlSession:session willPerformURLRequest:mockedURLRequest]); + OCMExpect([delegate urlSession:session didPerformURLRequest:mockedURLRequest withURLResponse:nil]); + XCTestExpectation *expectation = [self currentSelectorTestExpectation]; [[session performDataURLRequestAsync:mockedURLRequest forCommand:mockedCommand cancellationToken:nil] continueWithBlock:^id(BFTask *task) { @@ -251,6 +279,7 @@ - (void)testPerformDataRequestError { [self waitForTestExpectations]; OCMVerifyAll((id)mockedURLSession); + OCMVerifyAll(delegate); [mocks makeObjectsPerformSelector:@selector(stopMocking)]; } @@ -263,7 +292,8 @@ - (void)testFileUploadRequestPreCancel { BFCancellationTokenSource *cancellationTokenSource = [BFCancellationTokenSource cancellationTokenSource]; NSString *exampleFile = @"file.txt"; - PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession]; + id delegate = PFStrictProtocolMock(@protocol(PFURLSessionDelegate)); + PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession delegate:delegate]; XCTestExpectation *expectation = [self currentSelectorTestExpectation]; [cancellationTokenSource cancel]; @@ -290,6 +320,7 @@ - (void)testFileUploadSuccess { NSArray *mocks = @[ mockedURLSession, mockedURLRequest, mockedCommand ]; MockedSessionTask *mockedUploadTask = [[MockedSessionTask alloc] init]; + mockedUploadTask.originalRequest = mockedURLRequest; NSString *exampleFile = @"file.txt"; __block id sessionDelegate = nil; @@ -331,9 +362,13 @@ - (void)testFileUploadSuccess { didCompleteWithError:nil]; }; - PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession]; + id delegate = PFStrictProtocolMock(@protocol(PFURLSessionDelegate)); + PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession delegate:delegate]; sessionDelegate = (id)session; + OCMExpect([delegate urlSession:session willPerformURLRequest:mockedURLRequest]); + OCMExpect([delegate urlSession:session didPerformURLRequest:mockedURLRequest withURLResponse:[OCMArg isNotNil]]); + __block int lastProgress = 0; XCTestExpectation *expectation = [self currentSelectorTestExpectation]; @@ -354,6 +389,7 @@ - (void)testFileUploadSuccess { [self waitForTestExpectations]; OCMVerifyAll((id)mockedURLSession); + OCMVerifyAll(delegate); [mocks makeObjectsPerformSelector:@selector(stopMocking)]; } @@ -365,6 +401,7 @@ - (void)testFileUploadRequestCancellation { NSArray *mocks = @[ mockedURLSession, mockedURLRequest, mockedCommand ]; MockedSessionTask *mockedUploadTask = [[MockedSessionTask alloc] init]; + mockedUploadTask.originalRequest = mockedURLRequest; BFCancellationTokenSource *cancellationTokenSource = [BFCancellationTokenSource cancellationTokenSource]; NSString *exampleFile = @"file.txt"; @@ -415,9 +452,13 @@ - (void)testFileUploadRequestCancellation { [cancelExpectation fulfill]; }; - PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession]; + id delegate = PFProtocolMock(@protocol(PFURLSessionDelegate)); + PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession delegate:delegate]; sessionDelegate = (id)session; + OCMExpect([delegate urlSession:session willPerformURLRequest:mockedURLRequest]); + OCMExpect([delegate urlSession:session didPerformURLRequest:mockedURLRequest withURLResponse:[OCMArg isNotNil]]); + __block int lastProgress = 0; XCTestExpectation *expectation = [self currentSelectorTestExpectation]; @@ -437,6 +478,7 @@ - (void)testFileUploadRequestCancellation { [self waitForTestExpectations]; OCMVerifyAll((id)mockedURLSession); + OCMVerifyAll(delegate); [mocks makeObjectsPerformSelector:@selector(stopMocking)]; } @@ -447,6 +489,7 @@ - (void)testCaching { NSArray *mocks = @[ mockedURLSession, mockedURLRequest, mockedCommand ]; MockedSessionTask *mockedDataTask = [[MockedSessionTask alloc] init]; + mockedDataTask.originalRequest = mockedURLRequest; __block id sessionDelegate = nil; @@ -480,9 +523,13 @@ - (void)testCaching { completionHandler:^(NSCachedURLResponse *cached) { XCTAssertNil(cached); }]; }; - PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession]; + id delegate = PFProtocolMock(@protocol(PFURLSessionDelegate)); + PFURLSession *session = [PFURLSession sessionWithURLSession:mockedURLSession delegate:delegate]; sessionDelegate = (id)session; + OCMExpect([delegate urlSession:session willPerformURLRequest:mockedURLRequest]); + OCMExpect([delegate urlSession:session didPerformURLRequest:mockedURLRequest withURLResponse:[OCMArg isNotNil]]); + XCTestExpectation *expectation = [self currentSelectorTestExpectation]; [[session performDataURLRequestAsync:mockedURLRequest forCommand:mockedCommand cancellationToken:nil] continueWithBlock:^id(BFTask *task) { @@ -493,11 +540,14 @@ - (void)testCaching { [self waitForTestExpectations]; OCMVerifyAll((id)mockedURLSession); + OCMVerifyAll(delegate); [mocks makeObjectsPerformSelector:@selector(stopMocking)]; } - (void)testInvalidate { - PFURLSession *session = [PFURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]]; + id delegate = PFStrictProtocolMock(@protocol(PFURLSessionDelegate)); + PFURLSession *session = [PFURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] + delegate:delegate]; XCTAssertNoThrow([session invalidateAndCancel]); // lol? }