diff --git a/Tests/AFBufferedInputStreamProvider.h b/Tests/AFBufferedInputStreamProvider.h deleted file mode 100644 index ac66328..0000000 --- a/Tests/AFBufferedInputStreamProvider.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// AFDelayingInputStreamProvider.h -// AFNetworking Tests -// -// Created by Dev Floater 53 on 2013-07-02. -// Copyright (c) 2013 AFNetworking. All rights reserved. -// - -#import - -@interface AFBufferedInputStreamProvider : NSObject - -@property (nonatomic, readonly) NSUInteger bytesWritten; - -- (id) initWithData:(NSData *)data inputStream:(NSInputStream *__autoreleasing *)outInputStream; - -@end diff --git a/Tests/AFBufferedInputStreamProvider.m b/Tests/AFBufferedInputStreamProvider.m deleted file mode 100644 index 3dccee9..0000000 --- a/Tests/AFBufferedInputStreamProvider.m +++ /dev/null @@ -1,85 +0,0 @@ -// -// AFDelayingInputStreamProvider.m -// AFNetworking Tests -// -// Created by Dev Floater 53 on 2013-07-02. -// Copyright (c) 2013 AFNetworking. All rights reserved. -// - -#import "AFBufferedInputStreamProvider.h" - -@interface AFBufferedInputStreamProvider () -@property (nonatomic, strong) NSData *sourceData; - -@property (nonatomic, strong) NSInputStream *inputStream; -@property (nonatomic, strong) NSOutputStream *outputStream; -@end - -@implementation AFBufferedInputStreamProvider - -- (id) initWithData:(NSData *)data inputStream:(NSInputStream *__autoreleasing *)outInputStream { - NSParameterAssert(outInputStream); - self = [super init]; - if (!self) { - return nil; - } - - self.sourceData = data; - - CFReadStreamRef readStream; - CFWriteStreamRef writeStream; - CFStreamCreateBoundPair(NULL, &readStream, &writeStream, 16); - self.inputStream = CFBridgingRelease(readStream); - self.outputStream = CFBridgingRelease(writeStream); - self.outputStream.delegate = self; - [self.outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; - [self.outputStream open]; - *outInputStream = self.inputStream; - - return self; -} - -- (void)dealloc { - [self cleanup]; -} - -- (void) cleanup { - [self.outputStream close]; - self.outputStream.delegate = nil; - [self.outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; - self.outputStream = nil; - - [self.inputStream close]; - self.inputStream = nil; -} - -- (void) writeBytesIfPossible { - while ([self.outputStream hasSpaceAvailable] && self.bytesWritten < [self.sourceData length]) { - const uint8_t *bytes = [self.sourceData bytes]; - NSInteger res = [self.outputStream write:bytes+self.bytesWritten maxLength:[self.sourceData length]-self.bytesWritten]; - - if (res < 0) { - [self cleanup]; - return; - } - else { - _bytesWritten += res; - } - } - - if (self.bytesWritten >= [self.sourceData length]) { - [self cleanup]; - } -} - - -- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode { - if (aStream == self.outputStream && (eventCode & NSStreamEventHasSpaceAvailable)) { - [self writeBytesIfPossible]; - } - else if (eventCode & NSStreamEventErrorOccurred || eventCode & NSStreamEventEndEncountered) { - [self cleanup]; - } -} - -@end diff --git a/Tests/AFHTTPClientTests.m b/Tests/AFHTTPClientTests.m index 4ab1e00..353fcc8 100644 --- a/Tests/AFHTTPClientTests.m +++ b/Tests/AFHTTPClientTests.m @@ -21,7 +21,85 @@ // THE SOFTWARE. #import "AFNetworkingTests.h" -#import "AFBufferedInputStreamProvider.h" + +@interface AFBufferedInputStreamProvider : NSObject +@property (nonatomic, strong) NSData *data; +@property (nonatomic, strong) NSInputStream *inputStream; +@property (nonatomic, strong) NSOutputStream *outputStream; +@property (nonatomic, readonly) NSUInteger bytesWritten; + +- (id)initWithData:(NSData *)data; +@end + +@implementation AFBufferedInputStreamProvider + +- (id)initWithData:(NSData *)data { + self = [super init]; + if (!self) { + return nil; + } + + self.data = data; + + CFReadStreamRef readStream; + CFWriteStreamRef writeStream; + CFStreamCreateBoundPair(NULL, &readStream, &writeStream, 16); + + self.inputStream = CFBridgingRelease(readStream); + + self.outputStream = CFBridgingRelease(writeStream); + self.outputStream.delegate = self; + [self.outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + + [self.outputStream open]; + + return self; +} + +- (void)dealloc { + [self cleanup]; +} + +- (void)cleanup { + [self.outputStream close]; + self.outputStream.delegate = nil; + [self.outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes]; + _outputStream = nil; + + [self.inputStream close]; + _inputStream = nil; +} + +- (void)writeBytesIfPossible { + [self.data enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) { + NSInteger bytesWritten = [self.outputStream write:bytes maxLength:[self.data length] - self.bytesWritten]; + if (bytesWritten < 0) { + *stop = YES; + } else { + _bytesWritten += bytesWritten; + } + }]; + + if (self.bytesWritten >= [self.data length]) { + [self cleanup]; + } +} + +#pragma mark - NSStreamDelegate + +- (void)stream:(NSStream *)stream + handleEvent:(NSStreamEvent)eventCode +{ + if (stream == self.outputStream && (eventCode & NSStreamEventHasSpaceAvailable)) { + [self writeBytesIfPossible]; + } else if (eventCode & NSStreamEventErrorOccurred || eventCode & NSStreamEventEndEncountered) { + [self cleanup]; + } +} + +@end + +#pragma mark - @interface AFHTTPClientTests : SenTestCase @property (readwrite, nonatomic, strong) AFHTTPClient *client; @@ -351,21 +429,25 @@ } - (void)testMultipartUploadDoesNotPrematurelyCloseInputStream { - NSData *data = [@"Here is some data. Its length is larger than that of the buffer size of the bound stream pair." dataUsingEncoding:NSUTF8StringEncoding]; - NSInputStream *inputStream; - __block AFBufferedInputStreamProvider *streamProvider = [[AFBufferedInputStreamProvider alloc] initWithData:data inputStream:&inputStream]; + NSMutableString *mutableString = [NSMutableString string]; + for (NSUInteger i = 0; i < 10; i++) { + [mutableString appendString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"]; + } + + NSData *data = [mutableString dataUsingEncoding:NSUTF8StringEncoding]; + __block AFBufferedInputStreamProvider *streamProvider = [[AFBufferedInputStreamProvider alloc] initWithData:data]; __block NSUInteger bytesWritten = 0; - + NSInputStream *inputStream = streamProvider.inputStream; + NSMutableURLRequest *request = [self.client multipartFormRequestWithMethod:@"POST" path:@"/post" parameters:@{ @"foo": @"bar" } constructingBodyWithBlock:^(id formData) { [formData appendPartWithInputStream:inputStream name:@"data" fileName:@"string.txt" length:[data length] mimeType:@"text/plain"]; }]; - AFHTTPRequestOperation *operation = [self.client HTTPRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { + + AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; + operation.completionBlock = ^{ bytesWritten = streamProvider.bytesWritten; streamProvider = nil; - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - bytesWritten = streamProvider.bytesWritten; - streamProvider = nil; - }]; + }; [self.client enqueueHTTPRequestOperation:operation]; expect(operation.isFinished).will.beTruthy(); diff --git a/Tests/AFNetworking Tests.xcodeproj/project.pbxproj b/Tests/AFNetworking Tests.xcodeproj/project.pbxproj index 1294d83..6778f72 100644 --- a/Tests/AFNetworking Tests.xcodeproj/project.pbxproj +++ b/Tests/AFNetworking Tests.xcodeproj/project.pbxproj @@ -26,7 +26,6 @@ 29A9CE2117456336002360C8 /* AFJSONRequestOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29A9CE2017456336002360C8 /* AFJSONRequestOperationTests.m */; }; 29A9CE2217456336002360C8 /* AFJSONRequestOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 29A9CE2017456336002360C8 /* AFJSONRequestOperationTests.m */; }; 667B268117599C5800764906 /* AFImageRequestOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 667B268017599C5800764906 /* AFImageRequestOperationTests.m */; }; - A13DC4CF1783470C00F146CE /* AFBufferedInputStreamProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = A13DC4CE1783470C00F146CE /* AFBufferedInputStreamProvider.m */; }; A7DC62A917592E4800EBEC2F /* AFURLConnectionOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A7DC62A817592E4800EBEC2F /* AFURLConnectionOperationTests.m */; }; A7DC62AA17592E4800EBEC2F /* AFURLConnectionOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A7DC62A817592E4800EBEC2F /* AFURLConnectionOperationTests.m */; }; AC11A74923B64A3096ACADFC /* libPods-osx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 96A923755B00464187DEDBAF /* libPods-osx.a */; }; @@ -70,8 +69,6 @@ 55E73C267F33406A9F92476C /* libPods-ios.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ios.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 667B268017599C5800764906 /* AFImageRequestOperationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFImageRequestOperationTests.m; sourceTree = ""; }; 96A923755B00464187DEDBAF /* libPods-osx.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-osx.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - A13DC4CD1783470C00F146CE /* AFBufferedInputStreamProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFBufferedInputStreamProvider.h; sourceTree = ""; }; - A13DC4CE1783470C00F146CE /* AFBufferedInputStreamProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFBufferedInputStreamProvider.m; sourceTree = ""; }; A7DC62A817592E4800EBEC2F /* AFURLConnectionOperationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AFURLConnectionOperationTests.m; sourceTree = ""; }; F8C6F281174D2C6200B154D5 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Icon.png; path = ../Example/Icon.png; sourceTree = ""; }; F8D62D39175ABF5E00C717C3 /* AFMockURLProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AFMockURLProtocol.h; sourceTree = ""; }; @@ -174,8 +171,6 @@ 29A9CE2017456336002360C8 /* AFJSONRequestOperationTests.m */, 667B268017599C5800764906 /* AFImageRequestOperationTests.m */, 2580153A173EB3A70026AA6E /* AFHTTPClientTests.m */, - A13DC4CD1783470C00F146CE /* AFBufferedInputStreamProvider.h */, - A13DC4CE1783470C00F146CE /* AFBufferedInputStreamProvider.m */, ); name = Tests; sourceTree = ""; @@ -334,7 +329,6 @@ A7DC62A917592E4800EBEC2F /* AFURLConnectionOperationTests.m in Sources */, 667B268117599C5800764906 /* AFImageRequestOperationTests.m in Sources */, F8D62D3B175ABF5E00C717C3 /* AFMockURLProtocol.m in Sources */, - A13DC4CF1783470C00F146CE /* AFBufferedInputStreamProvider.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };