added download feature for iOS port

required libs: 
    * ZipArchive - Obj-C impl of zip
    * asi-http-request : http request help to assist with asynchoronous downloading of files
    * minizip : support for ZipArchive
    * 
Added default splash screen for iOS app.  (using the Wagic background to keep it neutral to module)

TODO: refine handling for iPad splash screen
    * add selection screen and input screen for location of downloadable content. (ie core files, image files, etc )
    * add support to opt out of backing up to iCloud for core files. Right now iOS will automatically backup all files under Documents folder to iCloud.  Consider only allowing player data to be backed up to iCloud.  All graphics and other assets are considered volatile.
This commit is contained in:
techdragon.nguyen@gmail.com
2011-12-11 07:40:22 +00:00
parent 071dca6b0a
commit 128c60bc2b
131 changed files with 27956 additions and 10 deletions

View File

@@ -0,0 +1,18 @@
//
// ASICloudFilesRequestTests.h
//
// Created by Michael Mayo on 1/6/10.
//
#import "ASITestCase.h"
@class ASINetworkQueue;
@interface ASICloudFilesRequestTests : ASITestCase {
ASINetworkQueue *networkQueue;
float progress;
}
@property (retain,nonatomic) ASINetworkQueue *networkQueue;
@end

View File

@@ -0,0 +1,338 @@
//
// ASICloudFilesRequestTests.m
//
// Created by Michael Mayo on 1/6/10.
//
#import "ASICloudFilesRequestTests.h"
// models
#import "ASICloudFilesContainer.h"
#import "ASICloudFilesObject.h"
// requests
#import "ASICloudFilesRequest.h"
#import "ASICloudFilesContainerRequest.h"
#import "ASICloudFilesObjectRequest.h"
#import "ASICloudFilesCDNRequest.h"
// Fill in these to run the tests that actually connect and manipulate objects on Cloud Files
static NSString *username = @"";
static NSString *apiKey = @"";
@implementation ASICloudFilesRequestTests
@synthesize networkQueue;
// Authenticate before any test if there's no auth token present
- (void)authenticate {
if (![ASICloudFilesRequest authToken]) {
[ASICloudFilesRequest setUsername:username];
[ASICloudFilesRequest setApiKey:apiKey];
[ASICloudFilesRequest authenticate];
}
}
// ASICloudFilesRequest
- (void)testAuthentication {
[self authenticate];
GHAssertNotNil([ASICloudFilesRequest authToken], @"Failed to authenticate and obtain authentication token");
GHAssertNotNil([ASICloudFilesRequest storageURL], @"Failed to authenticate and obtain storage URL");
GHAssertNotNil([ASICloudFilesRequest cdnManagementURL], @"Failed to authenticate and obtain CDN URL");
}
- (void)testDateParser {
ASICloudFilesRequest *request = [[[ASICloudFilesRequest alloc] init] autorelease];
NSDate *date = [request dateFromString:@"invalid date string"];
GHAssertNil(date, @"Should have failed to parse an invalid date string");
date = [request dateFromString:@"2009-11-04T19:46:20.192723"];
GHAssertNotNil(date, @"Failed to parse date string");
NSDateComponents *components = [[[NSDateComponents alloc] init] autorelease];
[components setYear:2009];
[components setMonth:11];
[components setDay:4];
[components setHour:19];
[components setMinute:46];
[components setSecond:20];
NSCalendar *calendar = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSDate *referenceDate = [calendar dateFromComponents:components];
// NSDateComponents has seconds as the smallest value, so we'll just check the created date is less than 1 second different from what we expect
NSTimeInterval timeDifference = [date timeIntervalSinceDate:referenceDate];
BOOL success = (timeDifference < 1.0);
GHAssertTrue(success, @"Parsed date incorrectly");
}
// ASICloudFilesContainerRequest
- (void)testAccountInfo {
[self authenticate];
ASICloudFilesContainerRequest *request = [ASICloudFilesContainerRequest accountInfoRequest];
[request startSynchronous];
GHAssertTrue([request containerCount] > 0, @"Failed to retrieve account info");
GHAssertTrue([request bytesUsed] > 0, @"Failed to retrieve account info");
}
- (void)testContainerList {
[self authenticate];
NSArray *containers = nil;
ASICloudFilesContainerRequest *containerListRequest = [ASICloudFilesContainerRequest listRequest];
[containerListRequest startSynchronous];
containers = [containerListRequest containers];
GHAssertTrue([containers count] > 0, @"Failed to list containers");
NSUInteger i;
for (i = 0; i < [containers count]; i++) {
ASICloudFilesContainer *container = [containers objectAtIndex:i];
GHAssertNotNil(container.name, @"Failed to parse container");
}
ASICloudFilesContainerRequest *limitContainerListRequest = [ASICloudFilesContainerRequest listRequestWithLimit:2 marker:nil];
[limitContainerListRequest startSynchronous];
containers = [limitContainerListRequest containers];
GHAssertTrue([containers count] == 2, @"Failed to limit container list");
}
- (void)testContainerCreate {
[self authenticate];
ASICloudFilesContainerRequest *createContainerRequest = [ASICloudFilesContainerRequest createContainerRequest:@"ASICloudFilesContainerTest"];
[createContainerRequest startSynchronous];
GHAssertTrue([createContainerRequest error] == nil, @"Failed to create container");
}
- (void)testContainerDelete {
[self authenticate];
ASICloudFilesContainerRequest *deleteContainerRequest = [ASICloudFilesContainerRequest deleteContainerRequest:@"ASICloudFilesContainerTest"];
[deleteContainerRequest startSynchronous];
GHAssertTrue([deleteContainerRequest error] == nil, @"Failed to delete container");
}
// ASICloudFilesObjectRequest
- (void)testContainerInfo {
[self authenticate];
// create a file first
ASICloudFilesContainerRequest *createContainerRequest = [ASICloudFilesContainerRequest createContainerRequest:@"ASICloudFilesTest"];
[createContainerRequest startSynchronous];
NSData *data = [@"this is a test" dataUsingEncoding:NSUTF8StringEncoding];
ASICloudFilesObjectRequest *putRequest
= [ASICloudFilesObjectRequest putObjectRequestWithContainer:@"ASICloudFilesTest"
objectPath:@"infotestfile.txt" contentType:@"text/plain"
objectData:data metadata:nil etag:nil];
[putRequest startSynchronous];
ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest containerInfoRequest:@"ASICloudFilesTest"];
[request startSynchronous];
GHAssertTrue([request containerObjectCount] > 0, @"Failed to retrieve container info");
GHAssertTrue([request containerBytesUsed] > 0, @"Failed to retrieve container info");
}
- (void)testObjectInfo {
[self authenticate];
ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest objectInfoRequest:@"ASICloudFilesTest" objectPath:@"infotestfile.txt"];
[request startSynchronous];
ASICloudFilesObject *object = [request object];
GHAssertNotNil(object, @"Failed to retrieve object");
GHAssertTrue([object.metadata count] > 0, @"Failed to parse metadata");
GHAssertTrue([object.metadata objectForKey:@"Test"] != nil, @"Failed to parse metadata");
}
- (void)testObjectList {
[self authenticate];
ASICloudFilesObjectRequest *objectListRequest = [ASICloudFilesObjectRequest listRequestWithContainer:@"ASICloudFilesTest"];
[objectListRequest startSynchronous];
NSArray *containers = [objectListRequest objects];
GHAssertTrue([containers count] > 0, @"Failed to list objects");
NSUInteger i;
for (i = 0; i < [containers count]; i++) {
ASICloudFilesObject *object = [containers objectAtIndex:i];
GHAssertNotNil(object.name, @"Failed to parse object");
}
}
- (void)testGetObject {
[self authenticate];
ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest getObjectRequestWithContainer:@"ASICloudFilesTest" objectPath:@"infotestfile.txt"];
[request startSynchronous];
ASICloudFilesObject *object = [request object];
GHAssertNotNil(object, @"Failed to retrieve object");
GHAssertNotNil(object.name, @"Failed to parse object name");
GHAssertTrue(object.bytes > 0, @"Failed to parse object bytes");
GHAssertNotNil(object.contentType, @"Failed to parse object content type");
GHAssertNotNil(object.lastModified, @"Failed to parse object last modified");
GHAssertNotNil(object.data, @"Failed to parse object data");
}
- (void)testPutObject {
[self authenticate];
ASICloudFilesContainerRequest *createContainerRequest
= [ASICloudFilesContainerRequest createContainerRequest:@"ASICloudFilesTest"];
[createContainerRequest startSynchronous];
NSData *data = [@"this is a test" dataUsingEncoding:NSUTF8StringEncoding];
ASICloudFilesObjectRequest *putRequest
= [ASICloudFilesObjectRequest putObjectRequestWithContainer:@"ASICloudFilesTest"
objectPath:@"puttestfile.txt" contentType:@"text/plain"
objectData:data metadata:nil etag:nil];
[putRequest startSynchronous];
GHAssertNil([putRequest error], @"Failed to PUT object");
ASICloudFilesObjectRequest *getRequest = [ASICloudFilesObjectRequest getObjectRequestWithContainer:@"ASICloudFilesTest" objectPath:@"puttestfile.txt"];
[getRequest startSynchronous];
ASICloudFilesObject *object = [getRequest object];
NSString *string = [[NSString alloc] initWithData:object.data encoding:NSASCIIStringEncoding];
GHAssertNotNil(object, @"Failed to retrieve new object");
GHAssertNotNil(object.name, @"Failed to parse object name");
GHAssertEqualStrings(object.name, @"puttestfile.txt", @"Failed to parse object name", @"Failed to parse object name");
GHAssertNotNil(object.data, @"Failed to parse object data");
GHAssertEqualStrings(string, @"this is a test", @"Failed to parse object data", @"Failed to parse object data");
ASICloudFilesContainerRequest *deleteContainerRequest = [ASICloudFilesContainerRequest deleteContainerRequest:@"ASICloudFilesTest"];
[deleteContainerRequest startSynchronous];
// Now put the object from a file
createContainerRequest = [ASICloudFilesContainerRequest createContainerRequest:@"ASICloudFilesTest"];
[createContainerRequest startSynchronous];
NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"cloudfile"];
[data writeToFile:filePath atomically:NO];
putRequest = [ASICloudFilesObjectRequest putObjectRequestWithContainer:@"ASICloudFilesTest" objectPath:@"puttestfile.txt" contentType:@"text/plain" file:filePath metadata:nil etag:nil];
[putRequest startSynchronous];
GHAssertNil([putRequest error], @"Failed to PUT object");
getRequest = [ASICloudFilesObjectRequest getObjectRequestWithContainer:@"ASICloudFilesTest" objectPath:@"puttestfile.txt"];
[getRequest startSynchronous];
object = [getRequest object];
GHAssertNotNil(object, @"Failed to retrieve new object");
GHAssertNotNil(object.name, @"Failed to parse object name");
GHAssertEqualStrings(object.name, @"puttestfile.txt", @"Failed to parse object name", @"Failed to parse object name");
GHAssertNotNil(object.data, @"Failed to parse object data");
GHAssertEqualStrings(string, @"this is a test", @"Failed to parse object data", @"Failed to parse object data");
[string release];
deleteContainerRequest = [ASICloudFilesContainerRequest deleteContainerRequest:@"ASICloudFilesTest"];
[deleteContainerRequest startSynchronous];
}
- (void)testPostObject {
[self authenticate];
NSMutableDictionary *metadata = [[NSMutableDictionary alloc] initWithCapacity:2];
[metadata setObject:@"test" forKey:@"Test"];
[metadata setObject:@"test" forKey:@"ASITest"];
ASICloudFilesObject *object = [ASICloudFilesObject object];
object.name = @"infotestfile.txt";
object.metadata = metadata;
ASICloudFilesObjectRequest *request = [ASICloudFilesObjectRequest postObjectRequestWithContainer:@"ASICloudFilesTest" object:object];
[request startSynchronous];
GHAssertTrue([request responseStatusCode] == 202, @"Failed to post object metadata");
[metadata release];
}
- (void)testDeleteObject {
[self authenticate];
ASICloudFilesObjectRequest *deleteRequest = [ASICloudFilesObjectRequest deleteObjectRequestWithContainer:@"ASICloudFilesTest" objectPath:@"puttestfile.txt"];
[deleteRequest startSynchronous];
GHAssertTrue([deleteRequest responseStatusCode] == 204, @"Failed to delete object");
}
#pragma mark -
#pragma mark CDN Tests
- (void)testCDNContainerInfo {
[self authenticate];
ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest containerInfoRequest:@"ASICloudFilesTest"];
[request startSynchronous];
GHAssertTrue([request responseStatusCode] == 204, @"Failed to retrieve CDN container info");
GHAssertTrue([request cdnEnabled], @"Failed to retrieve CDN container info");
GHAssertNotNil([request cdnURI], @"Failed to retrieve CDN container info");
GHAssertTrue([request cdnTTL] > 0, @"Failed to retrieve CDN container info");
}
- (void)testCDNContainerList {
[self authenticate];
ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest listRequest];
[request startSynchronous];
GHAssertNotNil([request containers], @"Failed to retrieve CDN container list");
}
- (void)testCDNContainerListWithParams {
[self authenticate];
ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest listRequestWithLimit:2 marker:nil enabledOnly:YES];
[request startSynchronous];
GHAssertNotNil([request containers], @"Failed to retrieve CDN container list");
GHAssertTrue([[request containers] count] == 2, @"Failed to retrieve limited CDN container list");
}
- (void)testCDNPut {
[self authenticate];
ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest putRequestWithContainer:@"ASICloudFilesTest"];
[request startSynchronous];
GHAssertNotNil([request cdnURI], @"Failed to PUT to CDN container");
}
- (void)testCDNPost {
[self authenticate];
ASICloudFilesCDNRequest *request = [ASICloudFilesCDNRequest postRequestWithContainer:@"ASICloudFilesTest" cdnEnabled:YES ttl:86600];
[request startSynchronous];
GHAssertNotNil([request cdnURI], @"Failed to POST to CDN container");
}
#pragma mark -
#pragma mark Memory Management
-(void)dealloc {
[networkQueue release];
[super dealloc];
}
@end

View File

@@ -0,0 +1,16 @@
//
// ASIDataCompressorTests.h
// Mac
//
// Created by Ben Copsey on 17/08/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASITestCase.h"
@interface ASIDataCompressorTests : ASITestCase {
}
@end

View File

@@ -0,0 +1,179 @@
//
// ASIDataCompressorTests.m
// Mac
//
// Created by Ben Copsey on 17/08/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
// Sadly these tests only work on Mac because of the dependency on NSTask, but I'm fairly sure this class should behave in the same way on iOS
#import "ASIDataCompressorTests.h"
#import "ASIDataCompressor.h"
#import "ASIDataDecompressor.h"
#import "ASIHTTPRequest.h"
@implementation ASIDataCompressorTests
- (void)setUp
{
NSFileManager *fileManager = [[[NSFileManager alloc] init] autorelease];
// Download a 1.7MB text file
NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"story.txt"];
if (![fileManager fileExistsAtPath:filePath] || [[[fileManager attributesOfItemAtPath:filePath error:NULL] objectForKey:NSFileSize] unsignedLongLongValue] < 1693961) {
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_hound_of_the_baskervilles.text"]];
[request setDownloadDestinationPath:[[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"story.txt"]];
[request startSynchronous];
}
}
- (void)testInflateData
{
NSString *originalString = [NSString stringWithContentsOfFile:[[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"story.txt"] encoding:NSUTF8StringEncoding error:NULL];
// Test in-memory inflate using uncompressData:error:
NSError *error = nil;
NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"uncompressed_file.txt"];
NSString *gzippedFilePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"uncompressed_file.txt.gz"];
[ASIHTTPRequest removeFileAtPath:gzippedFilePath error:&error];
if (error) {
GHFail(@"Failed to remove old file, cannot proceed with test");
}
[originalString writeToFile:filePath atomically:NO encoding:NSUTF8StringEncoding error:&error];
if (error) {
GHFail(@"Failed to write string, cannot proceed with test");
}
NSTask *task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath:@"/usr/bin/gzip"];
[task setArguments:[NSArray arrayWithObject:filePath]];
[task launch];
[task waitUntilExit];
NSData *deflatedData = [NSData dataWithContentsOfFile:gzippedFilePath];
NSData *inflatedData = [ASIDataDecompressor uncompressData:deflatedData error:&error];
if (error) {
GHFail(@"Inflate failed because %@",error);
}
NSString *inflatedString = [[[NSString alloc] initWithBytes:[inflatedData bytes] length:[inflatedData length] encoding:NSUTF8StringEncoding] autorelease];
BOOL success = [inflatedString isEqualToString:originalString];
GHAssertTrue(success,@"inflated data is not the same as original");
// Test file to file inflate
NSString *inflatedFilePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"inflated_file.txt"];
[ASIHTTPRequest removeFileAtPath:inflatedFilePath error:&error];
if (error) {
GHFail(@"Failed to remove old file, cannot proceed with test");
}
if (![ASIDataDecompressor uncompressDataFromFile:gzippedFilePath toFile:inflatedFilePath error:&error]) {
GHFail(@"Inflate failed because %@",error);
}
originalString = [NSString stringWithContentsOfFile:inflatedFilePath encoding:NSUTF8StringEncoding error:&error];
if (error) {
GHFail(@"Failed to read the inflated data, cannot proceed with test");
}
success = [inflatedString isEqualToString:originalString];
GHAssertTrue(success,@"inflated data is not the same as original");
}
- (void)testDeflateData
{
NSString *originalString = [NSString stringWithContentsOfFile:[[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"story.txt"] encoding:NSUTF8StringEncoding error:NULL];
// Test in-memory deflate using compressData:error:
NSError *error = nil;
NSData *deflatedData = [ASIDataCompressor compressData:[originalString dataUsingEncoding:NSUTF8StringEncoding] error:&error];
if (error) {
GHFail(@"Failed to deflate the data");
}
NSString *gzippedFilePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"uncompressed_file.txt.gz"];
[ASIHTTPRequest removeFileAtPath:gzippedFilePath error:&error];
if (error) {
GHFail(@"Failed to remove old file, cannot proceed with test");
}
[deflatedData writeToFile:gzippedFilePath options:0 error:&error];
if (error) {
GHFail(@"Failed to write data, cannot proceed with test");
}
NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"uncompressed_file.txt"];
[ASIHTTPRequest removeFileAtPath:filePath error:&error];
if (error) {
GHFail(@"Failed to remove old file, cannot proceed with test");
}
NSTask *task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath:@"/usr/bin/gzip"];
[task setArguments:[NSArray arrayWithObjects:@"-d",gzippedFilePath,nil]];
[task launch];
[task waitUntilExit];
NSString *inflatedString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
if (error) {
GHFail(@"Failed to read the inflated data, cannot proceed with test");
}
BOOL success = [inflatedString isEqualToString:originalString];
GHAssertTrue(success,@"inflated data is not the same as original");
// Test file to file deflate
[ASIHTTPRequest removeFileAtPath:gzippedFilePath error:&error];
if (![ASIDataCompressor compressDataFromFile:filePath toFile:gzippedFilePath error:&error]) {
GHFail(@"Deflate failed because %@",error);
}
[ASIHTTPRequest removeFileAtPath:filePath error:&error];
task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath:@"/usr/bin/gzip"];
[task setArguments:[NSArray arrayWithObjects:@"-d",gzippedFilePath,nil]];
[task launch];
[task waitUntilExit];
inflatedString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];
success = ([inflatedString isEqualToString:originalString]);
GHAssertTrue(success,@"deflate data is not the same as that generated by gzip");
// Test for bug https://github.com/pokeb/asi-http-request/issues/147
[ASIHTTPRequest removeFileAtPath:gzippedFilePath error:&error];
[ASIHTTPRequest removeFileAtPath:filePath error:&error];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://spaceharvest.com/i/screen6.png"]];
[request setDownloadDestinationPath:filePath];
[request startSynchronous];
if (![ASIDataCompressor compressDataFromFile:filePath toFile:gzippedFilePath error:&error]) {
GHFail(@"Deflate failed because %@",error);
}
unsigned long long originalFileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error] fileSize];
[ASIHTTPRequest removeFileAtPath:filePath error:&error];
task = [[[NSTask alloc] init] autorelease];
[task setLaunchPath:@"/usr/bin/gzip"];
[task setArguments:[NSArray arrayWithObjects:@"-d",gzippedFilePath,nil]];
[task launch];
[task waitUntilExit];
unsigned long long inflatedFileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&error] fileSize];
success = (originalFileSize == inflatedFileSize);
GHAssertTrue(success,@"inflated data is not the same size as the original");
}
@end

View File

@@ -0,0 +1,17 @@
//
// ASIDownloadCacheTests.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 03/05/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
#import "ASITestCase.h"
@interface ASIDownloadCacheTests : ASITestCase {
NSUInteger requestsFinishedCount;
BOOL requestRedirectedWasCalled;
}
@end

View File

@@ -0,0 +1,562 @@
//
// ASIDownloadCacheTests.m
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 03/05/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
#import "ASIDownloadCacheTests.h"
#import "ASIDownloadCache.h"
#import "ASIHTTPRequest.h"
// Stop clang complaining about undeclared selectors
@interface ASIDownloadCacheTests ()
- (void)runCacheOnlyCallsRequestFinishedOnceTest;
- (void)finishCached:(ASIHTTPRequest *)request;
- (void)runRedirectTest;
@end
@implementation ASIDownloadCacheTests
- (void)testDownloadCache
{
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIUseDefaultCachePolicy];
[ASIHTTPRequest setDefaultCache:nil];
// Ensure a request without a download cache does not pull from the cache
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request startSynchronous];
BOOL success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Used cached response when we shouldn't have");
// Make all requests use the cache
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
// Check a request isn't setting didUseCachedResponse when the data is not in the cache
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request startSynchronous];
success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Cached response should not have been available");
// Test read from the cache
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request startSynchronous];
success = [request didUseCachedResponse];
GHAssertTrue(success,@"Failed to use cached response");
// Test preventing reads from the cache
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:YES];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request setCachePolicy:ASIAskServerIfModifiedWhenStaleCachePolicy|ASIDoNotReadFromCacheCachePolicy];
[request startSynchronous];
success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Used the cache when reads were not enabled");
//Empty the cache
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
// Test preventing writes to the cache
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request setCachePolicy:ASIAskServerIfModifiedWhenStaleCachePolicy|ASIDoNotWriteToCacheCachePolicy];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request setCachePolicy:ASIAskServerIfModifiedWhenStaleCachePolicy];
[request startSynchronous];
success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Used cached response when the cache should have been empty");
// Test respecting etag
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/content-always-new"]];
[request startSynchronous];
success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Used cached response when we shouldn't have");
// Etag will be different on the second request
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/content-always-new"]];
// Note: we are forcing it to perform a conditional GET
[request setCachePolicy:ASIDoNotReadFromCacheCachePolicy|ASIAskServerIfModifiedCachePolicy];
[request startSynchronous];
success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Used cached response when we shouldn't have");
// Test ignoring server headers
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/no-cache"]];
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:NO];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/no-cache"]];
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:NO];
[request startSynchronous];
success = [request didUseCachedResponse];
GHAssertTrue(success,@"Failed to use cached response");
// Test ASIOnlyLoadIfNotCachedCachePolicy
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:YES];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/content-always-new"]];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[request startSynchronous];
success = [request didUseCachedResponse];
GHAssertTrue(success,@"Failed to use cached response");
// Test clearing the cache
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request startSynchronous];
success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Cached response should not have been available");
// Test ASIAskServerIfModifiedWhenStaleCachePolicy
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIUseDefaultCachePolicy];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/content-always-new"]];
[request setSecondsToCache:2];
[request startSynchronous];
// This request should not go to the network
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/content-always-new"]];
[request startSynchronous];
success = [request didUseCachedResponse];
GHAssertTrue(success,@"Failed to use cached response");
[NSThread sleepForTimeInterval:2];
// This request will perform a conditional GET
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/content-always-new"]];
[request setSecondsToCache:2];
[request startSynchronous];
success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Failed to use cached response");
// Test ASIFallbackToCacheIfLoadFailsCachePolicy
// Store something in the cache
[request setURL:[NSURL URLWithString:@"http://"]];
[request setResponseHeaders:[NSDictionary dictionaryWithObject:@"test" forKey:@"test"]];
[request setRawResponseData:(NSMutableData *)[@"test" dataUsingEncoding:NSUTF8StringEncoding]];
[[ASIDownloadCache sharedCache] storeResponseForRequest:request maxAge:0];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://"]];
[request setCachePolicy:ASIFallbackToCacheIfLoadFailsCachePolicy];
[request startSynchronous];
success = [request didUseCachedResponse];
GHAssertTrue(success,@"Failed to use cached response");
success = [[request responseString] isEqualToString:@"test"];
GHAssertTrue(success,@"Failed to read cached response");
success = [[[request responseHeaders] valueForKey:@"test"] isEqualToString:@"test"];
GHAssertTrue(success,@"Failed to read cached response headers");
// Remove the stuff from the cache, and try again
[request setURL:[NSURL URLWithString:@"http://"]];
[[ASIDownloadCache sharedCache] removeCachedDataForRequest:request];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://"]];
[request setCachePolicy:ASIFallbackToCacheIfLoadFailsCachePolicy];
[request startSynchronous];
success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Request says it used a cached response, but there wasn't one to use");
success = ([request error] != nil);
GHAssertTrue(success,@"Request had no error set");
// Cache some data
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"];
request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSString *path = [[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:request];
success = (path != nil);
GHAssertTrue(success,@"Cache failed to store data");
path = [[ASIDownloadCache sharedCache] pathToStoreCachedResponseHeadersForRequest:request];
success = (path != nil);
GHAssertTrue(success,@"Cache failed to store data");
// Make sure data gets removed
[[ASIDownloadCache sharedCache] removeCachedDataForURL:url];
path = [[ASIDownloadCache sharedCache] pathToCachedResponseDataForURL:url];
success = (path == nil);
GHAssertTrue(success,@"Cache failed to remove data");
path = [[ASIDownloadCache sharedCache] pathToCachedResponseHeadersForURL:url];
success = (path == nil);
GHAssertTrue(success,@"Cache failed to remove data");
// Test ASIDontLoadCachePolicy
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/content-always-new"]];
[request setCachePolicy:ASIDontLoadCachePolicy];
[request startSynchronous];
success = ![request error];
GHAssertTrue(success,@"Request had an error");
success = ![request contentLength];
GHAssertTrue(success,@"Request had a response");
}
- (void)testDefaultPolicy
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
BOOL success = ([request cachePolicy] == [[ASIDownloadCache sharedCache] defaultCachePolicy]);
GHAssertTrue(success,@"Failed to use the cache policy from the cache");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[request startSynchronous];
success = ([request cachePolicy] == ASIOnlyLoadIfNotCachedCachePolicy);
GHAssertTrue(success,@"Failed to use the cache policy from the cache");
}
- (void)testNoCache
{
// Test server no-cache headers
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
NSArray *cacheHeaders = [NSArray arrayWithObjects:@"cache-control/no-cache",@"cache-control/no-store",@"pragma/no-cache",nil];
for (NSString *cacheType in cacheHeaders) {
NSString *url = [NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/%@",cacheType];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:url]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
BOOL success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Data should not have been stored in the cache");
}
}
- (void)testSharedCache
{
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
// Make using the cache automatic
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"]];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"]];
[request startSynchronous];
BOOL success = [request didUseCachedResponse];
GHAssertTrue(success,@"Failed to use data cached in default cache");
[ASIHTTPRequest setDefaultCache:nil];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"]];
[request startSynchronous];
success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Should not have used data cached in default cache");
}
- (void)testExpiry
{
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIAskServerIfModifiedCachePolicy];
NSArray *headers = [NSArray arrayWithObjects:@"last-modified",@"etag",@"expires",@"max-age",nil];
for (NSString *header in headers) {
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/content-always-new/%@",header]]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
if ([header isEqualToString:@"last-modified"]) {
[NSThread sleepForTimeInterval:2];
}
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/content-always-new/%@",header]]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
BOOL success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Cached data should have expired");
}
}
- (void)testMaxAgeParsing
{
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIUseDefaultCachePolicy];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-control-max-age-parsing"]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-control-max-age-parsing"]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
BOOL success = [request didUseCachedResponse];
GHAssertTrue(success,@"Failed to use cached response");
}
- (void)testExtensionHandling
{
NSArray *extensions = [ASIDownloadCache fileExtensionsToHandleAsHTML];
for (NSString *extension in extensions) {
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://allseeing-i.com/file.%@",extension]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
NSString *path = [[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:request];
BOOL success = [[path pathExtension] isEqualToString:@"html"];
GHAssertTrue(success, @"Failed to use html extension on cached path for a resource we know a webview won't be able to open locally");
}
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
NSString *path = [[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:request];
BOOL success = [[path pathExtension] isEqualToString:@"html"];
GHAssertTrue(success, @"Failed to use html extension on cached path for a url without an extension");
url = [NSURL URLWithString:@"http://allseeing-i.com/i/logo.png"];
request = [ASIHTTPRequest requestWithURL:url];
path = [[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:request];
success = [[path pathExtension] isEqualToString:@"png"];
GHAssertTrue(success, @"Failed to preserve file extension on cached path");
}
- (void)testCustomExpiry
{
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIUseDefaultCachePolicy];
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:YES];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request setSecondsToCache:-2];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
BOOL success = ![request didUseCachedResponse];
GHAssertTrue(success,@"Cached data should have expired");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request setSecondsToCache:20];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cache-away"]];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
success = [request didUseCachedResponse];
GHAssertTrue(success,@"Cached data should have been used");
}
- (void)test304
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_(abridged).txt"];
// Test default cache policy
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIUseDefaultCachePolicy];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
BOOL success = ([request responseStatusCode] == 200);
GHAssertTrue(success,@"Failed to perform a conditional get");
success = [request didUseCachedResponse];
GHAssertTrue(success,@"Cached data should have been used");
success = ([[request responseData] length]);
GHAssertTrue(success,@"Response was empty");
// Test 304 updates expiry date
url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/content_not_modified_but_expires_tomorrow"];
request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
NSTimeInterval expiryTimestamp = [[[[ASIDownloadCache sharedCache] cachedResponseHeadersForURL:url] objectForKey:@"X-ASIHTTPRequest-Expires"] doubleValue];
// Wait to give the expiry date a chance to change
sleep(2);
request = [ASIHTTPRequest requestWithURL:url];
[request setCachePolicy:ASIAskServerIfModifiedCachePolicy];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request startSynchronous];
success = [request didUseCachedResponse];
GHAssertTrue(success, @"Cached data should have been used");
NSTimeInterval newExpiryTimestamp = [[[[ASIDownloadCache sharedCache] cachedResponseHeadersForURL:url] objectForKey:@"X-ASIHTTPRequest-Expires"] doubleValue];
NSLog(@"%@",[request responseString]);
success = (newExpiryTimestamp > expiryTimestamp);
GHAssertTrue(success, @"Failed to update expiry timestamp on 304");
}
- (void)testStringEncoding
{
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:NO];
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/Character-Encoding/UTF-16"];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
BOOL success = ([request responseEncoding] == NSUnicodeStringEncoding);
GHAssertTrue(success,@"Got the wrong encoding back, cannot proceed with test");
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
success = [request responseEncoding] == NSUnicodeStringEncoding;
GHAssertTrue(success,@"Failed to set the correct encoding on the cached response");
[ASIHTTPRequest setDefaultCache:nil];
}
- (void)testCookies
{
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:NO];
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/set_cookie"];
ASIHTTPRequest *request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
NSArray *cookies = [request responseCookies];
BOOL success = ([cookies count]);
GHAssertTrue(success,@"Got no cookies back, cannot proceed with test");
request = [[[ASIHTTPRequest alloc] initWithURL:url] autorelease];
[request startSynchronous];
NSUInteger i;
for (i=0; i<[cookies count]; i++) {
if (![[[cookies objectAtIndex:i] name] isEqualToString:[[[request responseCookies] objectAtIndex:i] name]]) {
GHAssertTrue(success,@"Failed to set response cookies correctly");
return;
}
}
[ASIHTTPRequest setDefaultCache:nil];
}
// Text fix for a bug where the didFinishSelector would be called twice for a cached response using ASIReloadIfDifferentCachePolicy
- (void)testCacheOnlyCallsRequestFinishedOnce
{
// Run this request on the main thread to force delegate calls to happen synchronously
[self performSelectorOnMainThread:@selector(runCacheOnlyCallsRequestFinishedOnceTest) withObject:nil waitUntilDone:YES];
}
- (void)runCacheOnlyCallsRequestFinishedOnceTest
{
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/i/logo.png"]];
[request setCachePolicy:ASIUseDefaultCachePolicy];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request setDelegate:self];
[request startSynchronous];
requestsFinishedCount = 0;
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/i/logo.png"]];
[request setCachePolicy:ASIUseDefaultCachePolicy];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request setDidFinishSelector:@selector(finishCached:)];
[request setDelegate:self];
[request startSynchronous];
BOOL success = (requestsFinishedCount == 1);
GHAssertTrue(success,@"didFinishSelector called more than once");
}
- (void)finishCached:(ASIHTTPRequest *)request
{
requestsFinishedCount++;
}
- (void)testRedirect
{
// Run this request on the main thread to force delegate calls to happen synchronously
[self performSelectorOnMainThread:@selector(runRedirectTest) withObject:nil waitUntilDone:YES];
}
- (void)runRedirectTest
{
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICacheForSessionDurationCacheStoragePolicy];
[[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
[[ASIDownloadCache sharedCache] setDefaultCachePolicy:ASIUseDefaultCachePolicy];
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cached-redirect"]];
[request startSynchronous];
BOOL success = ([[[request url] absoluteString] isEqualToString:@"http://allseeing-i.com/i/logo.png"]);
GHAssertTrue(success,@"Request did not redirect correctly, cannot proceed with test");
requestRedirectedWasCalled = NO;
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/cached-redirect"]];
[request setDelegate:self];
[request startSynchronous];
success = ([request didUseCachedResponse]);
GHAssertTrue(success,@"Failed to cache final response");
GHAssertTrue(requestRedirectedWasCalled,@"Failed to call requestRedirected");
}
- (void)requestRedirected:(ASIHTTPRequest *)redirected
{
requestRedirectedWasCalled = YES;
}
- (void)request:(ASIHTTPRequest *)request willRedirectToURL:(NSURL *)newURL
{
BOOL success = ([[newURL absoluteString] isEqualToString:@"http://allseeing-i.com/i/logo.png"]);
GHAssertTrue(success,@"Request did not redirect correctly, cannot proceed with test");
success = ([request didUseCachedResponse]);
GHAssertTrue(success,@"Failed to cache redirect response");
[request redirectToURL:newURL];
}
- (void)testCachedFileOverwritten
{
// Test for https://github.com/pokeb/asi-http-request/pull/211
// This test ensures that items in the cache are correctly overwritten when a downloadDestinationPath is set,
// and they need to be copied to the cache at the end of the request
// This url returns different content every time
NSURL *url = [NSURL URLWithString:@"http://asi/ASIHTTPRequest/tests/random-content"];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request setSecondsToCache:0.5f];
[request startSynchronous];
NSString *path = [[ASIDownloadCache sharedCache] pathToCachedResponseDataForURL:url];
NSString *content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
sleep(1);
request = [ASIHTTPRequest requestWithURL:url];
[request setDownloadCache:[ASIDownloadCache sharedCache]];
[request setDownloadDestinationPath:[[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"test.html"]];
[request startSynchronous];
NSString *content2 = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
BOOL success = ![content isEqualToString:content2];
GHAssertTrue(success, @"Failed to overwrite response in cache");
}
@end

View File

@@ -0,0 +1,24 @@
//
// ASIFormDataRequestTests.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 08/11/2008.
// Copyright 2008 All-Seeing Interactive. All rights reserved.
//
#import "ASITestCase.h"
@interface ASIFormDataRequestTests : ASITestCase {
float progress;
}
- (void)testDefaultMethod;
- (void)testPostWithFileUpload;
- (void)testEmptyData;
- (void)testSubclass;
- (void)testURLEncodedPost;
- (void)testCharset;
- (void)testPUT;
- (void)testCopy;
@end

View File

@@ -0,0 +1,299 @@
//
// ASIFormDataRequestTests.m
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 08/11/2008.
// Copyright 2008 All-Seeing Interactive. All rights reserved.
//
#import "ASIFormDataRequestTests.h"
#import "ASIFormDataRequest.h"
// Used for subclass test
@interface ASIFormDataRequestSubclass : ASIFormDataRequest {}
@end
@implementation ASIFormDataRequestSubclass;
@end
@implementation ASIFormDataRequestTests
-(void)testDefaultMethod
{
ASIFormDataRequest *request = [[[ASIFormDataRequest alloc] initWithURL:[NSURL URLWithString:@"http://wedontcare.com"]] autorelease];
GHAssertTrue([[request requestMethod] isEqualToString:@"POST"], @"Default request method should be POST");
}
- (void)testAddNilKeysAndValues
{
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/empty-post-value"]];
[request setPostValue:nil forKey:@"key1"];
[request setPostValue:@"value2" forKey:@"key2"];
[request setData:nil forKey:@"file1"];
[request setData:[@"hello" dataUsingEncoding:NSUTF8StringEncoding] forKey:@"file2"];
[request startSynchronous];
BOOL success = ([[request responseString] isEqualToString:@"key1: \r\nkey2: value2\r\nfile1: \r\nfile2: hello"]);
GHAssertTrue(success, @"Sent wrong data");
// Test nil key (no key or value should be sent to the server)
request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request addPostValue:@"value1" forKey:nil];
[request addPostValue:@"value2" forKey:@"key2"];
[request buildPostBody];
NSString *postBody = [[[NSString alloc] initWithData:[request postBody] encoding:NSUTF8StringEncoding] autorelease];
success = ([postBody isEqualToString:@"key2=value2"]);
GHAssertTrue(success, @"Sent wrong data");
}
- (void)testPostWithFileUpload
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/post"];
//Create a 32kb file
unsigned int size = 1024*32;
NSMutableData *data = [NSMutableData dataWithLength:size];
NSString *path = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"bigfile"];
[data writeToFile:path atomically:NO];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
NSDate *d = [NSDate date];
#if TARGET_OS_IPHONE
NSValue *v = [NSValue valueWithCGRect:CGRectMake(0, 0, 200, 200)];
#else
NSValue *v = [NSValue valueWithRect:NSMakeRect(0, 0, 200, 200)];
#endif
[request setPostValue:@"foo" forKey:@"post_var"];
[request setPostValue:d forKey:@"post_var2"];
[request setPostValue:v forKey:@"post_var3"];
[request setFile:path forKey:@"file"];
[request startSynchronous];
BOOL success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"post_var: %@\r\npost_var2: %@\r\npost_var3: %@\r\nfile_name: %@\r\nfile_size: %hu\r\ncontent_type: %@",@"foo",d,v,@"bigfile",size,@"application/octet-stream"]]);
GHAssertTrue(success,@"Failed to upload the correct data (using local file)");
//Try the same with the raw data
request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request setPostValue:@"foo" forKey:@"post_var"];
[request setPostValue:d forKey:@"post_var2"];
[request setPostValue:v forKey:@"post_var3"];
[request setData:data forKey:@"file"];
[request startSynchronous];
success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"post_var: %@\r\npost_var2: %@\r\npost_var3: %@\r\nfile_name: %@\r\nfile_size: %hu\r\ncontent_type: %@",@"foo",d,v,@"file",size,@"application/octet-stream"]]);
GHAssertTrue(success,@"Failed to upload the correct data (using NSData)");
//Post with custom content-type and file name
request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request setPostValue:@"foo" forKey:@"post_var"];
[request setPostValue:d forKey:@"post_var2"];
[request setPostValue:v forKey:@"post_var3"];
[request setFile:path withFileName:@"myfile" andContentType:@"text/plain" forKey:@"file"];
[request startSynchronous];
success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"post_var: %@\r\npost_var2: %@\r\npost_var3: %@\r\nfile_name: %@\r\nfile_size: %hu\r\ncontent_type: %@",@"foo",d,v,@"myfile",size,@"text/plain"]]);
GHAssertTrue(success,@"Failed to send the correct content-type / file name");
//Post raw data with custom content-type and file name
request = [[[ASIFormDataRequest alloc] initWithURL:url] autorelease];
[request setPostValue:@"foo" forKey:@"post_var"];
[request setPostValue:d forKey:@"post_var2"];
[request setPostValue:v forKey:@"post_var3"];
[request setData:data withFileName:@"myfile" andContentType:@"text/plain" forKey:@"file"];
[request startSynchronous];
success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"post_var: %@\r\npost_var2: %@\r\npost_var3: %@\r\nfile_name: %@\r\nfile_size: %hu\r\ncontent_type: %@",@"foo",d,v,@"myfile",size,@"text/plain"]]);
GHAssertTrue(success,@"Failed to send the correct content-type / file name");
}
// Test fix for bug where setting an empty string for a form post value would cause the rest of the post body to be ignored (because an NSOutputStream won't like it if you try to write 0 bytes)
- (void)testEmptyData
{
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/post-empty"]];
[request setPostValue:@"hello" forKey:@"a_non_empty_string"];
[request setPostValue:@"" forKey:@"zzz_empty_string"];
[request setPostValue:@"there" forKey:@"xxx_non_empty_string"];
[request setShouldStreamPostDataFromDisk:YES];
[request buildPostBody];
[request startSynchronous];
BOOL success = ([[request responseString] isEqualToString:@"a_non_empty_string: hello\r\nzzz_empty_string: \r\nxxx_non_empty_string: there"]);
GHAssertTrue(success,@"Failed to send the correct post data");
}
// Ensure class convenience constructor returns an instance of our subclass
- (void)testSubclass
{
ASIFormDataRequestSubclass *instance = [ASIFormDataRequestSubclass requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
BOOL success = [instance isKindOfClass:[ASIFormDataRequestSubclass class]];
GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
}
- (void)testURLEncodedPost
{
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/url-encoded-post"]];
[request setPostValue:@"value1" forKey:@"value1"];
[request setPostValue:@"(%20 ? =)" forKey:@"value2"];
[request setPostValue:@"£100.00" forKey:@"value3"];
[request setPostValue:@"" forKey:@"value4"];
[request setPostValue:@"&??aaa=//ciaoèèè" forKey:@"teskey&aa"];
[request setShouldStreamPostDataFromDisk:YES];
[request setPostFormat:ASIURLEncodedPostFormat];
[request startSynchronous];
BOOL success = ([[request responseString] isEqualToString:@"value1: value1\r\nvalue2: (%20 ? =)\r\nvalue3: £100.00\r\nvalue4: \r\nteskey&aa: &??aaa=//ciaoèèè"]);
GHAssertTrue(success,@"Failed to send the correct post data");
}
- (void)testCharset
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/formdata-charset"];
NSString *testString = @"£££s don't seem to buy me many €€€s these days";
// Test the default (UTF-8) with a url-encoded request
NSString *charset = @"utf-8";
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:testString forKey:@"value"];
[request startSynchronous];
BOOL success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"Got data in %@: %@",charset,testString]]);
GHAssertTrue(success,@"Failed to correctly encode the data");
// Test the default (UTF-8) with a multipart/form-data request
request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:testString forKey:@"value"];
[request setPostFormat:ASIMultipartFormDataPostFormat];
[request startSynchronous];
success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"Got data in %@: %@",charset,testString]]);
GHAssertTrue(success,@"Failed to correctly encode the data");
// Test a different charset
testString = @"£££s don't seem to buy me many $$$s these days";
charset = @"iso-8859-1";
request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:testString forKey:@"value"];
[request setStringEncoding:NSISOLatin1StringEncoding];
[request startSynchronous];
success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"Got data in %@: %@",charset,testString]]);
GHAssertTrue(success,@"Failed to correctly encode the data");
// And again with multipart/form-data request
request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:testString forKey:@"value"];
[request setPostFormat:ASIMultipartFormDataPostFormat];
[request setStringEncoding:NSISOLatin1StringEncoding];
[request startSynchronous];
success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"Got data in %@: %@",charset,testString]]);
GHAssertTrue(success,@"Failed to correctly encode the data");
// Once more for luck
charset = @"windows-1252";
request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:testString forKey:@"value"];
[request setStringEncoding:NSWindowsCP1252StringEncoding];
[request startSynchronous];
success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"Got data in %@: %@",charset,testString]]);
GHAssertTrue(success,@"Failed to correctly encode the data");
request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:testString forKey:@"value"];
[request setPostFormat:ASIMultipartFormDataPostFormat];
[request setStringEncoding:NSWindowsCP1252StringEncoding];
[request startSynchronous];
success = ([[request responseString] isEqualToString:[NSString stringWithFormat:@"Got data in %@: %@",charset,testString]]);
GHAssertTrue(success,@"Failed to correctly encode the data");
// Ensure charset isn't added to file post (GH issue 36)
request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/Tests/return-raw-request"]];
[request setData:[@"test 123" dataUsingEncoding:NSUTF8StringEncoding] forKey:@"file"];
[request setRequestMethod:@"PUT"];
[request startSynchronous];
success = ([[request responseString] rangeOfString:@"charset=utf-8"].location == NSNotFound);
GHAssertTrue(success,@"Sent a charset header for an uploaded file");
}
- (void)testPUT
{
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/Tests/put_form_data"]];
[request setRequestMethod:@"PUT"];
[request setPostValue:@"cheep cheep" forKey:@"hello"];
[request startSynchronous];
NSString *expectedResponse = [[[NSString alloc] initWithBytes:[[request postBody] bytes] length:[[request postBody] length] encoding:[request stringEncoding]] autorelease];
BOOL success = ([[request responseString] isEqualToString:expectedResponse]);
GHAssertTrue(success,@"Failed to send form data using PUT");
// Ensure that other methods still default to POST
request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/Tests/put_form_data"]];
[request setRequestMethod:@"DELETE"];
[request setPostValue:@"cheep cheep" forKey:@"hello"];
[request startSynchronous];
success = ([[request responseString] isEqualToString:@"Got POST instead"]);
GHAssertTrue(success,@"Failed to send form data using PUT");
}
- (void)testCopy
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
ASIFormDataRequest *request2 = [request copy];
GHAssertNotNil(request2,@"Failed to create a copy");
[pool release];
BOOL success = ([request2 retainCount] == 1);
GHAssertTrue(success,@"Failed to create a retained copy");
success = ([request2 isKindOfClass:[ASIFormDataRequest class]]);
GHAssertTrue(success,@"Copy is of wrong class");
[request2 release];
}
- (void)testMultipleValuesForASingleKey
{
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/multiple-values"]];
[request addPostValue:@"here" forKey:@"test_value[]"];
[request addPostValue:@"are" forKey:@"test_value[]"];
[request addPostValue:@"some" forKey:@"test_value[]"];
[request addPostValue:@"values" forKey:@"test_value[]"];
NSString *path1 = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"file1.txt"];
NSString *path2 = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"file2.txt"];
[@"hello" writeToFile:path1 atomically:NO encoding:NSUTF8StringEncoding error:nil];
[@"there" writeToFile:path2 atomically:NO encoding:NSUTF8StringEncoding error:nil];
[request addFile:path1 forKey:@"test_file[]"];
[request addFile:path2 forKey:@"test_file[]"];
[request startSynchronous];
NSString *expectedOutput = @"here\r\nare\r\nsome\r\nvalues\r\nfile1.txt\r\nfile2.txt\r\n";
BOOL success = [[request responseString] isEqualToString:expectedOutput];
GHAssertTrue(success,@"Failed to send the correct data");
// Check data replaces older data
request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/single-values"]];
[request addPostValue:@"here" forKey:@"test_value[]"];
[request addPostValue:@"are" forKey:@"test_value[]"];
[request addPostValue:@"some" forKey:@"test_value[]"];
[request addPostValue:@"values" forKey:@"test_value[]"];
[request setPostValue:@"this is new data" forKey:@"test_value[]"];
[request addFile:path1 forKey:@"test_file[]"];
[request addFile:path2 forKey:@"test_file[]"];
[request setData:[@"this is new data" dataUsingEncoding:NSUTF8StringEncoding] forKey:@"test_file[]"];
[request startSynchronous];
expectedOutput = @"this is new data\r\nfile\r\n";
success = [[request responseString] isEqualToString:expectedOutput];
GHAssertTrue(success,@"Failed to send the correct data");
}
@end

View File

@@ -0,0 +1,64 @@
//
// ASIHTTPRequestTests.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 01/08/2008.
// Copyright 2008 All-Seeing Interactive. All rights reserved.
//
#import "ASITestCase.h"
@class ASIHTTPRequest;
@interface ASIHTTPRequestTests : ASITestCase {
float progress;
BOOL started;
BOOL finished;
BOOL failed;
BOOL receivedResponseHeaders;
NSMutableData *responseData;
}
- (void)testBasicDownload;
- (void)testBase64Encode;
- (void)testDelegateMethods;
- (void)testConditionalGET;
- (void)testException;
- (void)testTimeOut;
- (void)testRequestMethod;
- (void)testHTTPVersion;
- (void)testUserAgent;
- (void)testAutomaticRedirection;
- (void)test30xCrash;
- (void)testUploadContentLength;
- (void)testDownloadContentLength;
- (void)testFileDownload;
- (void)testDownloadProgress;
- (void)testUploadProgress;
- (void)testCookies;
- (void)testRemoveCredentialsFromKeychain;
- (void)testBasicAuthentication;
- (void)testDigestAuthentication;
- (void)testNTLMHandshake;
- (void)testCharacterEncoding;
- (void)testCompressedResponse;
- (void)testCompressedResponseDownloadToFile;
- (void)test000SSL;
- (void)testRedirectPreservesSession;
- (void)testTooMuchRedirection;
- (void)testRedirectToNewDomain;
- (void)test303Redirect;
- (void)testSubclass;
- (void)testTimeOutWithoutDownloadDelegate;
- (void)testThrottlingDownloadBandwidth;
- (void)testThrottlingUploadBandwidth;
#if TARGET_OS_IPHONE
- (void)testReachability;
#endif
- (void)testAutomaticRetry;
- (void)testCloseConnection;
- (void)testPersistentConnections;
- (void)testNilPortCredentialsMatching;
@property (retain, nonatomic) NSMutableData *responseData;
@end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,83 @@
//
// ASINetworkQueueTests.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 08/11/2008.
// Copyright 2008 All-Seeing Interactive. All rights reserved.
//
#import "ASITestCase.h"
/*
IMPORTANT
Code that appears in these tests is not for general purpose use.
You should not use [networkQueue waitUntilAllOperationsAreFinished] or [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]] in your own software.
They are used here to force a queue to operate synchronously to simplify writing the tests.
IMPORTANT
*/
@class ASIHTTPRequest;
@class ASINetworkQueue;
@interface ASINetworkQueueTests : ASITestCase {
ASIHTTPRequest *requestThatShouldFail;
BOOL complete;
BOOL request_didfail;
BOOL request_succeeded;
float progress;
int addedRequests;
NSOperationQueue *immediateCancelQueue;
NSMutableArray *failedRequests;
NSMutableArray *finishedRequests;
ASINetworkQueue *releaseTestQueue;
ASINetworkQueue *cancelQueue;
int authenticationPromptCount;
ASINetworkQueue *postQueue;
ASINetworkQueue *testNTLMQueue;
ASINetworkQueue *addMoreRequestsQueue;
int requestsFinishedCount;
BOOL started;
BOOL finished;
BOOL failed;
BOOL headFailed;
BOOL receivedResponseHeaders;
int queueFinishedCallCount;
}
- (void)testFailure;
- (void)testFailureCancelsOtherRequests;
- (void)testDownloadProgress;
- (void)testUploadProgress;
- (void)testProgressWithAuthentication;
- (void)testWithNoListener;
- (void)testPartialResume;
- (void)testImmediateCancel;
- (void)setProgress:(float)newProgress;
- (void)testSubclass;
- (void)testQueueReleaseOnRequestComplete;
- (void)testQueueReleaseOnQueueComplete;
- (void)testMultipleDownloadsThrottlingBandwidth;
- (void)testMultipleUploadsThrottlingBandwidth;
- (void)testDelegateAuthenticationCredentialsReuse;
- (void)testPOSTWithAuthentication;
- (void)testHEADFailure;
@property (retain) NSOperationQueue *immediateCancelQueue;
@property (retain) NSMutableArray *failedRequests;
@property (retain) NSMutableArray *finishedRequests;
@property (retain) ASINetworkQueue *releaseTestQueue;
@property (retain) ASINetworkQueue *cancelQueue;
@property (retain) ASINetworkQueue *postQueue;
@property (retain) ASINetworkQueue *testNTLMQueue;
@property (retain) ASINetworkQueue *addMoreRequestsQueue;
@end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
//
// ASIS3RequestTests.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 12/07/2009.
// Copyright 2009 All-Seeing Interactive. All rights reserved.
//
#import "ASITestCase.h"
@class ASINetworkQueue;
@interface ASIS3RequestTests : ASITestCase {
ASINetworkQueue *networkQueue;
float progress;
}
- (void)testAuthenticationHeaderGeneration;
- (void)testREST;
- (void)testFailure;
- (void)testListRequest;
- (void)testSubclasses;
- (void)createTestBucket;
- (void)testCopy;
- (void)testHTTPS;
@property (retain,nonatomic) ASINetworkQueue *networkQueue;
@end

View File

@@ -0,0 +1,860 @@
//
// ASIS3RequestTests.m
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 12/07/2009.
// Copyright 2009 All-Seeing Interactive. All rights reserved.
//
#import "ASIS3RequestTests.h"
#import "ASINetworkQueue.h"
#import "ASIS3BucketObject.h"
#import "ASIS3ObjectRequest.h"
#import "ASIS3BucketRequest.h"
#import "ASIS3ServiceRequest.h"
// Fill in these to run the tests that actually connect and manipulate objects on S3
static NSString *secretAccessKey = @"";
static NSString *accessKey = @"";
// You should run these tests on a bucket that does not yet exist
static NSString *bucket = @"";
// Used for subclass test
@interface ASIS3ObjectRequestSubclass : ASIS3ObjectRequest {}
@end
@implementation ASIS3ObjectRequestSubclass;
@end
@interface ASIS3BucketRequestSubclass : ASIS3BucketRequest {}
@end
@implementation ASIS3BucketRequestSubclass;
@end
@interface ASIS3BucketObjectSubclass : ASIS3BucketObject {}
@end
@implementation ASIS3BucketObjectSubclass;
@end
// Stop clang complaining about undeclared selectors
@interface ASIS3RequestTests ()
- (void)GETRequestDone:(ASIHTTPRequest *)request;
- (void)GETRequestFailed:(ASIHTTPRequest *)request;
- (void)PUTRequestDone:(ASIHTTPRequest *)request;
- (void)PUTRequestFailed:(ASIHTTPRequest *)request;
- (void)DELETERequestDone:(ASIHTTPRequest *)request;
- (void)DELETERequestFailed:(ASIHTTPRequest *)request;
@end
@implementation ASIS3RequestTests
// All these tests are based on Amazon's examples at: http://docs.amazonwebservices.com/AmazonS3/2006-03-01/
- (void)testAuthenticationHeaderGeneration
{
NSString *exampleSecretAccessKey = @"uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o";
NSString *exampleAccessKey = @"0PN5J17HBGZHT7JJ3X82";
NSString *exampleBucket = @"johnsmith";
// Test list all my buckets
NSString *dateString = @"Wed, 28 Mar 2007 01:29:59 +0000";
ASIS3ServiceRequest *serviceRequest = [ASIS3ServiceRequest serviceRequest];
[serviceRequest setSecretAccessKey:exampleSecretAccessKey];
[serviceRequest setAccessKey:exampleAccessKey];
[serviceRequest setDateString:dateString];
[serviceRequest buildRequestHeaders];
BOOL success = [[[serviceRequest requestHeaders] valueForKey:@"Authorization"] isEqualToString:@"AWS 0PN5J17HBGZHT7JJ3X82:Db+gepJSUbZKwpx1FR0DLtEYoZA="];
GHAssertTrue(success,@"Failed to generate the correct authorisation header for a GET service request");
// Test GET
NSString *key = @"photos/puppy.jpg";
dateString = @"Tue, 27 Mar 2007 19:36:42 +0000";
ASIS3ObjectRequest *request = [ASIS3ObjectRequest requestWithBucket:exampleBucket key:key];
[request setDateString:dateString];
[request setSecretAccessKey:exampleSecretAccessKey];
[request setAccessKey:exampleAccessKey];
[request buildRequestHeaders];
success = [[[request requestHeaders] valueForKey:@"Authorization"] isEqualToString:@"AWS 0PN5J17HBGZHT7JJ3X82:xXjDGYUmKxnwqr5KXNPGldn5LbA="];
GHAssertTrue(success,@"Failed to generate the correct authorisation header for a GET request");
// Test PUT
key = @"photos/puppy.jpg";
dateString = @"Tue, 27 Mar 2007 21:15:45 +0000";
request = [ASIS3ObjectRequest requestWithBucket:exampleBucket key:key];
[request setRequestMethod:@"PUT"];
[request setMimeType:@"image/jpeg"];
[request setDateString:dateString];
[request setSecretAccessKey:exampleSecretAccessKey];
[request setAccessKey:exampleAccessKey];
[request buildRequestHeaders];
success = [[[request requestHeaders] valueForKey:@"Authorization"] isEqualToString:@"AWS 0PN5J17HBGZHT7JJ3X82:hcicpDDvL9SsO6AkvxqmIWkmOuQ="];
GHAssertTrue(success,@"Failed to generate the correct authorisation header for a PUT request");
// Test List
dateString = @"Tue, 27 Mar 2007 19:42:41 +0000";
ASIS3BucketRequest *listRequest = [ASIS3BucketRequest requestWithBucket:exampleBucket];
[listRequest setPrefix:@"photos"];
[listRequest setMaxResultCount:50];
[listRequest setMarker:@"puppy"];
[listRequest setDateString:dateString];
[listRequest setSecretAccessKey:exampleSecretAccessKey];
[listRequest setAccessKey:exampleAccessKey];
[listRequest buildRequestHeaders];
success = [[[listRequest requestHeaders] valueForKey:@"Authorization"] isEqualToString:@"AWS 0PN5J17HBGZHT7JJ3X82:jsRt/rhG+Vtp88HrYL706QhE4w4="];
GHAssertTrue(success,@"Failed to generate the correct authorisation header for a list request");
// Test fetch ACL
dateString = @"Tue, 27 Mar 2007 19:44:46 +0000";
listRequest = [ASIS3BucketRequest requestWithBucket:exampleBucket subResource:@"acl"];
[listRequest setDateString:dateString];
[listRequest setSecretAccessKey:exampleSecretAccessKey];
[listRequest setAccessKey:exampleAccessKey];
[listRequest buildRequestHeaders];
success = [[[listRequest requestHeaders] valueForKey:@"Authorization"] isEqualToString:@"AWS 0PN5J17HBGZHT7JJ3X82:thdUi9VAkzhkniLj96JIrOPGi0g="];
GHAssertTrue(success,@"Failed to generate the correct authorisation header for a list request");
// Test Unicode keys
// Comment out this test for now, as the S3 example is relying on mixed-case hex-encoded characters in the url, which isn't going to be easy to replicate
// exampleBucket = @"dictionary";
// key = @"français/préfère";
// dateString = @"Wed, 28 Mar 2007 01:49:49 +0000";
// request = [ASIS3ObjectRequest requestWithBucket:exampleBucket key:key];
// [request setDateString:dateString];
// [request setSecretAccessKey:exampleSecretAccessKey];
// [request setAccessKey:exampleAccessKey];
// [request buildRequestHeaders];
// success = [[[request requestHeaders] valueForKey:@"Authorization"] isEqualToString:@"AWS 0PN5J17HBGZHT7JJ3X82:dxhSBHoI6eVSPcXJqEghlUzZMnY="];
//GHAssertTrue(success,@"Failed to generate the correct authorisation header for a list request");
}
- (void)testFailure
{
// Needs expanding to cover more failure states - this is just a test to ensure Amazon's error description is being added to the error
// We're actually going to try with the Amazon example details, but the request will fail because the date is old
NSString *exampleSecretAccessKey = @"uV3F3YluFJax1cknvbcGwgjvx4QpvB+leU8dUj2o";
NSString *exampleAccessKey = @"0PN5J17HBGZHT7JJ3X82";
NSString *exampleBucket = @"johnsmith";
NSString *key = @"photos/puppy.jpg";
NSString *dateString = @"Tue, 27 Mar 2007 19:36:42 +0000";
ASIS3Request *request = [ASIS3ObjectRequest requestWithBucket:exampleBucket key:key];
[request setDateString:dateString];
[request setSecretAccessKey:exampleSecretAccessKey];
[request setAccessKey:exampleAccessKey];
[request startSynchronous];
GHAssertNotNil([request error],@"Failed to generate an error when the request was not correctly signed");
BOOL success = ([[request error] code] == ASIS3ResponseErrorType);
GHAssertTrue(success,@"Generated error had the wrong error code");
success = ([[[request error] localizedDescription] isEqualToString:@"The difference between the request time and the current time is too large."]);
GHAssertTrue(success,@"Generated error had the wrong description");
// Ensure a bucket request will correctly parse an error from S3
request = [ASIS3BucketRequest requestWithBucket:exampleBucket];
[request setDateString:dateString];
[request setSecretAccessKey:exampleSecretAccessKey];
[request setAccessKey:exampleAccessKey];
[request startSynchronous];
GHAssertNotNil([request error],@"Failed to generate an error when the request was not correctly signed");
success = ([[request error] code] == ASIS3ResponseErrorType);
GHAssertTrue(success,@"Generated error had the wrong error code");
success = ([[[request error] localizedDescription] isEqualToString:@"The difference between the request time and the current time is too large."]);
GHAssertTrue(success,@"Generated error had the wrong description");
// Ensure a service request will correctly parse an error from S3
request = [ASIS3ServiceRequest serviceRequest];
[request setDateString:dateString];
[request setSecretAccessKey:exampleSecretAccessKey];
[request setAccessKey:exampleAccessKey];
[request startSynchronous];
GHAssertNotNil([request error],@"Failed to generate an error when the request was not correctly signed");
success = ([[request error] code] == ASIS3ResponseErrorType);
GHAssertTrue(success,@"Generated error had the wrong error code");
success = ([[[request error] localizedDescription] isEqualToString:@"The difference between the request time and the current time is too large."]);
GHAssertTrue(success,@"Generated error had the wrong description");
}
- (void)createTestBucket
{
// Test creating a bucket
ASIS3BucketRequest *bucketRequest = [ASIS3BucketRequest PUTRequestWithBucket:bucket];
[bucketRequest setSecretAccessKey:secretAccessKey];
[bucketRequest setAccessKey:accessKey];
[bucketRequest startSynchronous];
GHAssertNil([bucketRequest error],@"Failed to create a bucket");
}
// To run this test, uncomment and fill in your S3 access details
- (void)testREST
{
[self createTestBucket];
BOOL success = (![secretAccessKey isEqualToString:@""] && ![accessKey isEqualToString:@""] && ![bucket isEqualToString:@""]);
GHAssertTrue(success,@"You need to supply your S3 access details to run the REST test (see the top of ASIS3RequestTests.m)");
// Test creating a bucket
ASIS3BucketRequest *bucketRequest = [ASIS3BucketRequest PUTRequestWithBucket:bucket];
[bucketRequest setSecretAccessKey:secretAccessKey];
[bucketRequest setAccessKey:accessKey];
[bucketRequest startSynchronous];
GHAssertNil([bucketRequest error],@"Failed to create a bucket");
// List buckets to make sure the bucket is there
ASIS3ServiceRequest *serviceRequest = [ASIS3ServiceRequest serviceRequest];
[serviceRequest setSecretAccessKey:secretAccessKey];
[serviceRequest setAccessKey:accessKey];
[serviceRequest startSynchronous];
GHAssertNil([serviceRequest error],@"Failed to fetch the list of buckets from S3");
BOOL foundBucket = NO;
for (ASIS3Bucket *theBucket in [serviceRequest buckets]) {
if ([[theBucket name] isEqualToString:bucket]) {
foundBucket = YES;
break;
}
}
GHAssertTrue(foundBucket,@"Failed to retrive the newly-created bucket in a list of buckets");
NSString *key = @"test";
// Create the file
NSString *text = @"This is my content";
NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"testfile.txt"];
[[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO];
// PUT the file
ASIS3ObjectRequest *request = [ASIS3ObjectRequest PUTRequestForFile:filePath withBucket:bucket key:key];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request setStorageClass:ASIS3StorageClassReducedRedundancy];
[request startSynchronous];
success = [[request responseString] isEqualToString:@""];
GHAssertTrue(success,@"Failed to PUT a file to S3");
// GET the file
request = [ASIS3ObjectRequest requestWithBucket:bucket key:key];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
success = [[request responseString] isEqualToString:@"This is my content"];
GHAssertTrue(success,@"Failed to GET the correct data from S3");
// Test fetch subresource
request = [ASIS3ObjectRequest requestWithBucket:bucket key:key subResource:@"acl"];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
success = ([[request responseString] rangeOfString:@"<AccessControlPolicy"].location != NSNotFound);
GHAssertTrue(success,@"Failed to GET a subresource");
// COPY the file
request = [ASIS3ObjectRequest COPYRequestFromBucket:bucket key:key toBucket:bucket key:@"test-copy"];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
GHAssertNil([request error],@"Failed to COPY a file");
// GET the copy
request = [ASIS3ObjectRequest requestWithBucket:bucket key:@"test-copy"];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
success = [[request responseString] isEqualToString:@"This is my content"];
GHAssertTrue(success,@"Failed to GET the correct data from S3");
// HEAD the copy
request = [ASIS3ObjectRequest HEADRequestWithBucket:bucket key:@"test-copy"];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
success = [[request responseString] isEqualToString:@""];
GHAssertTrue(success,@"Got a response body for a HEAD request");
// Test listing the objects in this bucket
ASIS3BucketRequest *listRequest = [ASIS3BucketRequest requestWithBucket:bucket];
[listRequest setSecretAccessKey:secretAccessKey];
[listRequest setAccessKey:accessKey];
[listRequest startSynchronous];
GHAssertNil([listRequest error],@"Failed to download a list from S3");
success = [[listRequest objects] count];
GHAssertTrue(success,@"The file didn't show up in the list");
// Test again with a prefix query
listRequest = [ASIS3BucketRequest requestWithBucket:bucket];
[listRequest setPrefix:@"test"];
[listRequest setSecretAccessKey:secretAccessKey];
[listRequest setAccessKey:accessKey];
[listRequest startSynchronous];
GHAssertNil([listRequest error],@"Failed to download a list from S3");
success = [[listRequest objects] count];
GHAssertTrue(success,@"The file didn't show up in the list");
// DELETE the file
request = [ASIS3ObjectRequest requestWithBucket:bucket key:key];
[request setSecretAccessKey:secretAccessKey];
[request setRequestMethod:@"DELETE"];
[request setAccessKey:accessKey];
[request startSynchronous];
success = [[request responseString] isEqualToString:@""];
GHAssertTrue(success,@"Failed to DELETE the file from S3");
// (Also DELETE the copy we made)
request = [ASIS3ObjectRequest requestWithBucket:bucket key:@"test-copy"];
[request setSecretAccessKey:secretAccessKey];
[request setRequestMethod:@"DELETE"];
[request setAccessKey:accessKey];
[request startSynchronous];
success = [[request responseString] isEqualToString:@""];
GHAssertTrue(success,@"Failed to DELETE the copy from S3");
// Attempt to COPY the file, even though it is no longer there
request = [ASIS3ObjectRequest COPYRequestFromBucket:bucket key:key toBucket:bucket key:@"test-copy"];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
GHAssertNotNil([request error],@"Failed generate an error for what should have been a failed COPY");
success = [[[request error] localizedDescription] isEqualToString:@"The specified key does not exist."];
GHAssertTrue(success, @"Got the wrong error message");
// PUT some data
NSData *data = [@"Hello" dataUsingEncoding:NSUTF8StringEncoding];
request = [ASIS3ObjectRequest PUTRequestForData:data withBucket:bucket key:key];
[request setMimeType:@"text/plain"];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
success = [[request responseString] isEqualToString:@""];
GHAssertTrue(success,@"Failed to PUT data to S3");
// GET the data to check it uploaded properly
request = [ASIS3ObjectRequest requestWithBucket:bucket key:key];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
success = [[request responseString] isEqualToString:@"Hello"];
GHAssertTrue(success,@"Failed to GET the correct data from S3");
// clean up (Delete it)
request = [ASIS3ObjectRequest requestWithBucket:bucket key:key];
[request setSecretAccessKey:secretAccessKey];
[request setRequestMethod:@"DELETE"];
[request setAccessKey:accessKey];
[request startSynchronous];
success = [[request responseString] isEqualToString:@""];
GHAssertTrue(success,@"Failed to DELETE the file from S3");
// Delete the bucket
bucketRequest = [ASIS3BucketRequest DELETERequestWithBucket:bucket];
[bucketRequest setSecretAccessKey:secretAccessKey];
[bucketRequest setAccessKey:accessKey];
[bucketRequest startSynchronous];
GHAssertNil([bucketRequest error],@"Failed to delete a bucket");
}
// Will upload a file to S3, gzipping it before uploading
// The file will be stored deflate, and automatically inflated when downloaded
// This means the file will take up less storage space, and will upload and download faster
// The file should still be accessible by any HTTP client that supports gzipped responses (eg browsers, NSURLConnection, etc)
- (void)testGZippedContent
{
[self createTestBucket];
BOOL success = (![secretAccessKey isEqualToString:@""] && ![accessKey isEqualToString:@""] && ![bucket isEqualToString:@""]);
GHAssertTrue(success,@"You need to supply your S3 access details to run the gzipped put test (see the top of ASIS3RequestTests.m)");
// Create the file
NSString *text = @"This is my content This is my content This is my content This is my content This is my content This is my content";
NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:@"testfile.txt"];
[[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO];
NSString *key = @"gzipped-data";
ASIS3ObjectRequest *request = [ASIS3ObjectRequest PUTRequestForFile:filePath withBucket:bucket key:key];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request setShouldCompressRequestBody:YES];
[request setAccessPolicy:ASIS3AccessPolicyPublicRead]; // We'll make it public
[request startSynchronous];
success = [[request responseString] isEqualToString:@""];
GHAssertTrue(success,@"Failed to PUT the gzipped file");
// GET the file
request = [ASIS3ObjectRequest requestWithBucket:bucket key:key];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
success = [[request responseString] isEqualToString:text];
GHAssertTrue(success,@"Failed to GET the correct data from S3");
success = [[[request responseHeaders] valueForKey:@"Content-Encoding"] isEqualToString:@"gzip"];
GHAssertTrue(success,@"Failed to GET the correct data from S3");
// Now grab the data using something other than ASIHTTPRequest to ensure other HTTP clients can parse the gzipped content
NSData *data = [NSURLConnection sendSynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@.s3.amazonaws.com/gzipped-data",bucket]]] returningResponse:NULL error:NULL];
NSString *string = [[[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding] autorelease];
success = [string isEqualToString:text];
GHAssertTrue(success,@"Failed to GET the correct data from S3");
// Cleanup
request = [ASIS3ObjectRequest DELETERequestWithBucket:bucket key:key];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
}
- (void)testListRequest
{
[self createTestBucket];
BOOL success = (![secretAccessKey isEqualToString:@""] && ![accessKey isEqualToString:@""] && ![bucket isEqualToString:@""]);
GHAssertTrue(success,@"You need to supply your S3 access details to run the list test (see the top of ASIS3RequestTests.m)");
// Firstly, create and upload 5 files
int i;
for (i=0; i<5; i++) {
NSString *text = [NSString stringWithFormat:@"This is the content of file #%hi",i];
NSString *filePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:[NSString stringWithFormat:@"%hi.txt",i]];
[[text dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:NO];
NSString *key = [NSString stringWithFormat:@"test-file/%hi",i];
ASIS3ObjectRequest *request = [ASIS3ObjectRequest PUTRequestForFile:filePath withBucket:bucket key:key];
[request setSecretAccessKey:secretAccessKey];
[request setAccessKey:accessKey];
[request startSynchronous];
GHAssertNil([request error],@"Give up on list request test - failed to upload a file");
}
// Test common prefixes
ASIS3BucketRequest *listRequest = [ASIS3BucketRequest requestWithBucket:bucket];
[listRequest setSecretAccessKey:secretAccessKey];
[listRequest setAccessKey:accessKey];
[listRequest setDelimiter:@"/"];
[listRequest startSynchronous];
GHAssertNil([listRequest error],@"Failed to download a list from S3");
success = NO;
for (NSString *prefix in [listRequest commonPrefixes]) {
if ([prefix isEqualToString:@"test-file/"]) {
success = YES;
}
}
GHAssertTrue(success,@"Failed to obtain a list of common prefixes");
// Test truncation
listRequest = [ASIS3BucketRequest requestWithBucket:bucket];
[listRequest setSecretAccessKey:secretAccessKey];
[listRequest setAccessKey:accessKey];
[listRequest setMaxResultCount:1];
[listRequest startSynchronous];
GHAssertTrue([listRequest isTruncated],@"Failed to identify what should be a truncated list of results");
// Test urls are built correctly when requesting a subresource
listRequest = [ASIS3BucketRequest requestWithBucket:bucket subResource:@"acl"];
[listRequest setSecretAccessKey:secretAccessKey];
[listRequest setAccessKey:accessKey];
[listRequest setDelimiter:@"/"];
[listRequest setPrefix:@"foo"];
[listRequest setMarker:@"bar"];
[listRequest setMaxResultCount:5];
[listRequest buildURL];
NSString *expectedURL = [NSString stringWithFormat:@"http://%@.s3.amazonaws.com/?acl&prefix=foo&marker=bar&delimiter=/&max-keys=5",bucket];
success = ([[[listRequest url] absoluteString] isEqualToString:expectedURL]);
GHAssertTrue(success,@"Generated the wrong url when requesting a subresource");
// Now get a list of the files
listRequest = [ASIS3BucketRequest requestWithBucket:bucket];
[listRequest setPrefix:@"test-file"];
[listRequest setSecretAccessKey:secretAccessKey];
[listRequest setAccessKey:accessKey];
[listRequest startSynchronous];
GHAssertNil([listRequest error],@"Failed to download a list from S3");
success = ([[listRequest objects] count] == 5);
GHAssertTrue(success,@"List did not contain all files");
// Please don't use an autoreleased operation queue with waitUntilAllOperationsAreFinished in your own code unless you're writing a test like this one
// (The end result is no better than using synchronous requests) thx - Ben :)
ASINetworkQueue *queue = [[[ASINetworkQueue alloc] init] autorelease];
// Test fetching all the items
[queue setRequestDidFinishSelector:@selector(GETRequestDone:)];
[queue setRequestDidFailSelector:@selector(GETRequestFailed:)];
[queue setDelegate:self];
for (ASIS3BucketObject *object in [listRequest objects]) {
ASIS3ObjectRequest *request = [object GETRequest];
[request setAccessKey:accessKey];
[request setSecretAccessKey:secretAccessKey];
[queue addOperation:request];
}
[queue go];
[queue waitUntilAllOperationsAreFinished];
// Test uploading new files for all the items
[queue setRequestDidFinishSelector:@selector(PUTRequestDone:)];
[queue setRequestDidFailSelector:@selector(PUTRequestFailed:)];
[queue setDelegate:self];
i=0;
// For each one, we'll just upload the same content again
for (ASIS3BucketObject *object in [listRequest objects]) {
NSString *oldFilePath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:[NSString stringWithFormat:@"%hi.txt",i]];;
ASIS3Request *request = [object PUTRequestWithFile:oldFilePath];
[request setAccessKey:accessKey];
[request setSecretAccessKey:secretAccessKey];
[queue addOperation:request];
i++;
}
[queue go];
[queue waitUntilAllOperationsAreFinished];
// Test deleting all the items
[queue setRequestDidFinishSelector:@selector(DELETERequestDone:)];
[queue setRequestDidFailSelector:@selector(DELETERequestFailed:)];
[queue setDelegate:self];
i=0;
for (ASIS3BucketObject *object in [listRequest objects]) {
ASIS3ObjectRequest *request = [object DELETERequest];
[request setAccessKey:accessKey];
[request setSecretAccessKey:secretAccessKey];
[queue addOperation:request];
i++;
}
[queue go];
[queue waitUntilAllOperationsAreFinished];
// Grab the list again, it should be empty now
listRequest = [ASIS3BucketRequest requestWithBucket:bucket];
[listRequest setPrefix:@"test-file"];
[listRequest setSecretAccessKey:secretAccessKey];
[listRequest setAccessKey:accessKey];
[listRequest startSynchronous];
GHAssertNil([listRequest error],@"Failed to download a list from S3");
success = ([[listRequest objects] count] == 0);
GHAssertTrue(success,@"List contained files that should have been deleted");
}
- (void)GETRequestDone:(ASIS3Request *)request
{
NSString *expectedContent = [NSString stringWithFormat:@"This is the content of file #%@",[[[request url] absoluteString] lastPathComponent]];
BOOL success = ([[request responseString] isEqualToString:expectedContent]);
GHAssertTrue(success,@"Got the wrong content when downloading one of the files");
}
- (void)GETRequestFailed:(ASIS3Request *)request
{
GHAssertTrue(NO,@"GET request failed for one of the items in the list");
}
- (void)PUTRequestDone:(ASIS3Request *)request
{
}
- (void)PUTRequestFailed:(ASIS3Request *)request
{
GHAssertTrue(NO,@"PUT request failed for one of the items in the list");
}
- (void)DELETERequestDone:(ASIS3Request *)request
{
}
- (void)DELETERequestFailed:(ASIS3Request *)request
{
GHAssertTrue(NO,@"DELETE request failed for one of the items in the list");
}
// Ensure class convenience constructors return an instance of our subclass
- (void)testSubclasses
{
ASIS3ObjectRequestSubclass *instance = [ASIS3ObjectRequestSubclass requestWithBucket:@"bucket" key:@"key"];
BOOL success = [instance isKindOfClass:[ASIS3ObjectRequestSubclass class]];
GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
instance = [ASIS3ObjectRequestSubclass PUTRequestForFile:@"/file" withBucket:@"bucket" key:@"key"];
success = [instance isKindOfClass:[ASIS3ObjectRequestSubclass class]];
GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
instance = [ASIS3ObjectRequestSubclass DELETERequestWithBucket:@"bucket" key:@"key"];
success = [instance isKindOfClass:[ASIS3ObjectRequestSubclass class]];
GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
instance = [ASIS3ObjectRequestSubclass COPYRequestFromBucket:@"bucket" key:@"key" toBucket:@"bucket" key:@"key2"];
success = [instance isKindOfClass:[ASIS3ObjectRequestSubclass class]];
GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
instance = [ASIS3ObjectRequestSubclass HEADRequestWithBucket:@"bucket" key:@"key"];
success = [instance isKindOfClass:[ASIS3ObjectRequestSubclass class]];
GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
ASIS3BucketRequestSubclass *instance2 = [ASIS3BucketRequestSubclass requestWithBucket:@"bucket"];
success = [instance2 isKindOfClass:[ASIS3BucketRequestSubclass class]];
GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
ASIS3BucketObjectSubclass *instance3 = [ASIS3BucketObjectSubclass objectWithBucket:@"bucket"];
success = [instance3 isKindOfClass:[ASIS3BucketObjectSubclass class]];
GHAssertTrue(success,@"Convenience constructor failed to return an instance of the correct class");
}
- (void)s3RequestFailed:(ASIHTTPRequest *)request
{
GHFail(@"Request failed - cannot continue with test");
[[self networkQueue] cancelAllOperations];
}
- (void)s3QueueFinished:(ASINetworkQueue *)queue
{
// BOOL success = (progress == 1.0);
// GHAssertTrue(success,@"Failed to update progress properly");
}
- (void)testQueueProgress
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/i/logo.png"]];
[request startSynchronous];
NSData *data = [request responseData];
[self createTestBucket];
// Upload objects
progress = 0;
[[self networkQueue] cancelAllOperations];
[self setNetworkQueue:[ASINetworkQueue queue]];
[[self networkQueue] setDelegate:self];
[[self networkQueue] setRequestDidFailSelector:@selector(s3RequestFailed:)];
[[self networkQueue] setQueueDidFinishSelector:@selector(s3QueueFinished:)];
[[self networkQueue] setUploadProgressDelegate:self];
[[self networkQueue] setShowAccurateProgress:YES];
[[self networkQueue] setMaxConcurrentOperationCount:1];
int i;
for (i=0; i<5; i++) {
NSString *key = [NSString stringWithFormat:@"stuff/file%hi.txt",i+1];
ASIS3ObjectRequest *s3Request = [ASIS3ObjectRequest PUTRequestForData:data withBucket:bucket key:key];
[s3Request setSecretAccessKey:secretAccessKey];
[s3Request setAccessKey:accessKey];
[s3Request setTimeOutSeconds:20];
[s3Request setNumberOfTimesToRetryOnTimeout:3];
[s3Request setMimeType:@"image/png"];
[[self networkQueue] addOperation:s3Request];
}
[[self networkQueue] go];
[[self networkQueue] waitUntilAllOperationsAreFinished];
// Download objects
progress = 0;
[[self networkQueue] cancelAllOperations];
[self setNetworkQueue:[ASINetworkQueue queue]];
[[self networkQueue] setDelegate:self];
[[self networkQueue] setRequestDidFailSelector:@selector(s3RequestFailed:)];
[[self networkQueue] setQueueDidFinishSelector:@selector(s3QueueFinished:)];
[[self networkQueue] setDownloadProgressDelegate:self];
[[self networkQueue] setShowAccurateProgress:YES];
for (i=0; i<5; i++) {
NSString *key = [NSString stringWithFormat:@"stuff/file%hi.txt",i+1];
ASIS3ObjectRequest *s3Request = [ASIS3ObjectRequest requestWithBucket:bucket key:key];
[s3Request setSecretAccessKey:secretAccessKey];
[s3Request setAccessKey:accessKey];
NSString *downloadPath = [[self filePathForTemporaryTestFiles] stringByAppendingPathComponent:[NSString stringWithFormat:@"%hi.jpg",i+1]];
[s3Request setDownloadDestinationPath:downloadPath];
[[self networkQueue] addOperation:s3Request];
}
[[self networkQueue] go];
[[self networkQueue] waitUntilAllOperationsAreFinished];
progress = 0;
// Delete objects
progress = 0;
[[self networkQueue] cancelAllOperations];
[self setNetworkQueue:[ASINetworkQueue queue]];
[[self networkQueue] setDelegate:self];
[[self networkQueue] setRequestDidFailSelector:@selector(s3RequestFailed:)];
[[self networkQueue] setShowAccurateProgress:YES];
for (i=0; i<5; i++) {
NSString *key = [NSString stringWithFormat:@"stuff/file%hi.txt",i+1];
ASIS3ObjectRequest *s3Request = [ASIS3ObjectRequest DELETERequestWithBucket:bucket key:key];
[s3Request setSecretAccessKey:secretAccessKey];
[s3Request setAccessKey:accessKey];
[[self networkQueue] addOperation:s3Request];
}
[[self networkQueue] go];
[[self networkQueue] waitUntilAllOperationsAreFinished];
}
// Will be called on Mac OS
- (void)setDoubleValue:(double)newProgress;
{
progress = (float)newProgress;
}
- (void)setProgress:(float)newProgress;
{
progress = newProgress;
}
- (void)testCopy
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
ASIS3ObjectRequest *request = [ASIS3ObjectRequest requestWithBucket:@"foo" key:@"eep"];
ASIS3ObjectRequest *request2 = [request copy];
GHAssertNotNil(request2,@"Failed to create a copy");
[pool release];
BOOL success = ([request2 retainCount] > 0);
GHAssertTrue(success,@"Failed to create a retained copy");
success = ([request2 isKindOfClass:[ASIS3Request class]]);
GHAssertTrue(success,@"Copy is of wrong class");
[request2 release];
pool = [[NSAutoreleasePool alloc] init];
ASIS3BucketRequest *request3 = [ASIS3BucketRequest requestWithBucket:@"foo"];
ASIS3BucketRequest *request4 = [request3 copy];
GHAssertNotNil(request4,@"Failed to create a copy");
[pool release];
success = ([request4 retainCount] > 0);
GHAssertTrue(success,@"Failed to create a retained copy");
success = ([request4 isKindOfClass:[ASIS3BucketRequest class]]);
GHAssertTrue(success,@"Copy is of wrong class");
[request4 release];
pool = [[NSAutoreleasePool alloc] init];
ASIS3BucketObject *bucketObject = [ASIS3BucketObject objectWithBucket:@"foo"];
ASIS3BucketObject *bucketObject2 = [bucketObject copy];
GHAssertNotNil(bucketObject2,@"Failed to create a copy");
[pool release];
success = ([bucketObject2 retainCount] > 0);
GHAssertTrue(success,@"Failed to create a retained copy");
[bucketObject2 release];
}
- (void)testHTTPS
{
[ASIS3Request setSharedAccessKey:accessKey];
[ASIS3Request setSharedSecretAccessKey:secretAccessKey];
// Create a bucket
ASIS3Request *request = [ASIS3BucketRequest PUTRequestWithBucket:bucket];
[request setRequestScheme:ASIS3RequestSchemeHTTPS];
[request startSynchronous];
GHAssertNil([request error],@"Failed to create a bucket");
// PUT something in it
NSString *key = @"king";
request = [ASIS3ObjectRequest PUTRequestForData:[@"fink" dataUsingEncoding:NSUTF8StringEncoding] withBucket:bucket key:key];
[request setRequestScheme:ASIS3RequestSchemeHTTPS];
[request startSynchronous];
BOOL success = [[request responseString] isEqualToString:@""];
GHAssertTrue(success,@"Failed to PUT some data into S3");
// GET it
request = [ASIS3ObjectRequest requestWithBucket:bucket key:key];
[request setRequestScheme:ASIS3RequestSchemeHTTPS];
[request startSynchronous];
success = [[request responseString] isEqualToString:@"fink"];
GHAssertTrue(success,@"Failed to GET the correct data from S3");
// DELETE it
request = [ASIS3ObjectRequest DELETERequestWithBucket:bucket key:@"king"];
[request setRequestScheme:ASIS3RequestSchemeHTTPS];
[request startSynchronous];
success = [[request responseString] isEqualToString:@""];
GHAssertTrue(success,@"Failed to DELETE the object from S3");
// Delete the bucket
request = [ASIS3BucketRequest DELETERequestWithBucket:bucket];
[request setRequestScheme:ASIS3RequestSchemeHTTPS];
[request startSynchronous];
GHAssertNil([request error],@"Failed to delete a bucket");
[ASIS3Request setSharedAccessKey:nil];
[ASIS3Request setSharedSecretAccessKey:nil];
}
// Ideally this test would actually parse the ACL XML and check it, but for now it just makes sure S3 doesn't return an error
- (void)testCannedACLs
{
[ASIS3Request setSharedAccessKey:accessKey];
[ASIS3Request setSharedSecretAccessKey:secretAccessKey];
// Create a bucket
ASIS3Request *request = [ASIS3BucketRequest PUTRequestWithBucket:bucket];
[request setRequestScheme:ASIS3RequestSchemeHTTPS];
[request startSynchronous];
GHAssertNil([request error],@"Failed to create a bucket");
NSArray *ACLs = [NSArray arrayWithObjects:ASIS3AccessPolicyPrivate,ASIS3AccessPolicyPublicRead,ASIS3AccessPolicyPublicReadWrite,ASIS3AccessPolicyAuthenticatedRead,ASIS3AccessPolicyBucketOwnerRead,ASIS3AccessPolicyBucketOwnerFullControl,nil];
for (NSString *cannedACL in ACLs) {
// PUT object
NSString *key = @"king";
request = [ASIS3ObjectRequest PUTRequestForData:[@"fink" dataUsingEncoding:NSUTF8StringEncoding] withBucket:bucket key:key];
[request setAccessPolicy:cannedACL];
[request startSynchronous];
GHAssertNil([request error],@"Failed to PUT some data into S3");
// GET object ACL
request = [ASIS3ObjectRequest requestWithBucket:bucket key:key subResource:@"acl"];
[request startSynchronous];
GHAssertNil([request error],@"Failed to fetch the object");
}
// DELETE it
request = [ASIS3ObjectRequest DELETERequestWithBucket:bucket key:@"king"];
[request setRequestScheme:ASIS3RequestSchemeHTTPS];
[request startSynchronous];
BOOL success = [[request responseString] isEqualToString:@""];
GHAssertTrue(success,@"Failed to DELETE the object from S3");
// Delete the bucket
request = [ASIS3BucketRequest DELETERequestWithBucket:bucket];
[request setRequestScheme:ASIS3RequestSchemeHTTPS];
[request startSynchronous];
GHAssertNil([request error],@"Failed to delete a bucket");
[ASIS3Request setSharedAccessKey:nil];
[ASIS3Request setSharedSecretAccessKey:nil];
}
@synthesize networkQueue;
@end

View File

@@ -0,0 +1,20 @@
//
// ASITestCase.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 26/07/2009.
// Copyright 2009 All-Seeing Interactive. All rights reserved.
//
#import <Foundation/Foundation.h>
#if TARGET_OS_IPHONE
#import <GHUnitIOS/GHUnit.h>
#else
#import <GHUnit/GHUnit.h>
#endif
@interface ASITestCase : GHTestCase {
}
- (NSString *)filePathForTemporaryTestFiles;
@end

View File

@@ -0,0 +1,23 @@
//
// ASITestCase.m
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 26/07/2009.
// Copyright 2009 All-Seeing Interactive. All rights reserved.
//
#import "ASITestCase.h"
@implementation ASITestCase
- (NSString *)filePathForTemporaryTestFiles
{
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"ASIHTTPRequest Test Files"];
if (![[NSFileManager defaultManager] fileExistsAtPath:path isDirectory:NULL]) {
[[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:NULL];
}
return path;
}
@end

View File

@@ -0,0 +1,16 @@
//
// ASIWebPageRequestTests.h
// Mac
//
// Created by Ben Copsey on 06/01/2011.
// Copyright 2011 All-Seeing Interactive. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASITestCase.h"
@interface ASIWebPageRequestTests : ASITestCase {
}
@end

View File

@@ -0,0 +1,41 @@
//
// ASIWebPageRequestTests.m
// Mac
//
// Created by Ben Copsey on 06/01/2011.
// Copyright 2011 All-Seeing Interactive. All rights reserved.
//
#import "ASIWebPageRequestTests.h"
#import "ASIWebPageRequest.h"
@implementation ASIWebPageRequestTests
- (void)testEncoding
{
NSArray *encodings = [NSArray arrayWithObjects:@"us-ascii",@"iso-8859-1",@"utf-16",@"utf-8",nil];
NSArray *expectedResponses = [NSArray arrayWithObjects:@"Hi there",@"Olá",@"你好",@"今日は",nil];
NSUInteger i;
for (i=0; i<[encodings count]; i++) {
ASIWebPageRequest *request = [ASIWebPageRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://allseeing-i.com/ASIHTTPRequest/tests/asiwebpagerequest/character-encoding/%@",[encodings objectAtIndex:i]]]];
[request setUserInfo:[NSDictionary dictionaryWithObject:[expectedResponses objectAtIndex:i] forKey:@"expected-response"]];
[request setDelegate:self];
[request setUrlReplacementMode:ASIReplaceExternalResourcesWithLocalURLs];
[request startAsynchronous];
}
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
if ([[request userInfo] objectForKey:@"expected-response"]) {
BOOL success = ([[request responseString] rangeOfString:[[request userInfo] objectForKey:@"expected-response"]].location != NSNotFound);
GHAssertTrue(success,@"Response HTML used wrong encoding");
}
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
GHAssertNil([request error],@"Request failed, cannot proceed with test");
}
@end

View File

@@ -0,0 +1,16 @@
//
// BlocksTests.h
// Mac
//
// Created by Ben Copsey on 18/10/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASITestCase.h"
@interface BlocksTests : ASITestCase {
}
@end

View File

@@ -0,0 +1,105 @@
//
// BlocksTests.m
// Mac
//
// Created by Ben Copsey on 18/10/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
#import "BlocksTests.h"
#import "ASIHTTPRequest.h"
@implementation BlocksTests
// ASIHTTPRequest always calls blocks on the main thread (just like it does with delegate methods)
// So, we'll force this request to run on the main thread so we can rely on blocks having been called before the request returns
- (BOOL)shouldRunOnMainThread { return YES; }
#if NS_BLOCKS_AVAILABLE
#if TARGET_OS_IPHONE
// It isn't safe to allow the view to deallocate on a thread other than the main thread / web thread, so this test is designed to cause a crash semi-reliably
- (void)testBlockMainThreadSafety
{
NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];
UIWebView *webView = [[[UIWebView alloc] initWithFrame:CGRectMake(0,0,200,200)] autorelease];
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setCompletionBlock:^ {[webView loadHTMLString:[request responseString] baseURL:url]; }];
[request startAsynchronous];
}
#endif
- (void)testBlocks
{
NSData *dataToSend = [@"This is my post body" dataUsingEncoding:NSUTF8StringEncoding];
__block BOOL started = NO;
__block BOOL receivedHeaders = NO;
__block BOOL complete = NO;
__block BOOL failed = NO;
__block unsigned long long totalBytesReceived = 0;
__block unsigned long long totalDownloadSize = 0;
__block unsigned long long totalBytesSent = 0;
__block unsigned long long totalUploadSize = 0;
NSMutableData *dataReceived = [NSMutableData data];
// There's actually no need for us to use '__block' here, because we aren't using the request inside any of our blocks, but it's good to get into the habit of doing this anyway.
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/blocks"]];
[request setStartedBlock:^{
started = YES;
}];
[request setHeadersReceivedBlock:^(NSDictionary *headers) {
receivedHeaders = YES;
}];
[request setCompletionBlock:^{
complete = YES;
}];
[request setFailedBlock:^{
failed = YES;
}];
[request setBytesReceivedBlock:^(unsigned long long length, unsigned long long total) {
totalBytesReceived += length;
}];
[request setDownloadSizeIncrementedBlock:^(long long length){
totalDownloadSize += length;
}];
[request setBytesSentBlock:^(unsigned long long length, unsigned long long total) {
totalBytesSent += length;
}];
[request setUploadSizeIncrementedBlock:^(long long length){
totalUploadSize += length;
}];
[request setDataReceivedBlock:^(NSData *data){
[dataReceived appendData:data];
}];
[request setRequestMethod:@"PUT"];
[request appendPostData:dataToSend];
[request startSynchronous];
GHAssertFalse(failed,@"Request failed, cannot proceed with test");
GHAssertTrue(started,@"Failed to call started block");
GHAssertTrue(receivedHeaders,@"Failed to call received headers block");
GHAssertTrue(complete,@"Failed to call completed block");
BOOL success = (totalBytesReceived == 457);
GHAssertTrue(success,@"Failed to call bytes received block, or got wrong amount of data");
success = (totalDownloadSize == 457);
GHAssertTrue(success,@"Failed to call download size increment block");
success = (totalBytesSent == [dataToSend length]);
GHAssertTrue(success,@"Failed to call bytes sent block");
success = (totalUploadSize == [dataToSend length]);
GHAssertTrue(success,@"Failed to call upload size increment block");
request = [ASIHTTPRequest requestWithURL:nil];
[request setFailedBlock:^{
failed = YES;
}];
[request startSynchronous];
GHAssertTrue(failed,@"Failed to call request failure block");
}
#endif
@end

View File

@@ -0,0 +1,21 @@
//
// ClientCertificateTests.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 18/08/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
// Currently, these tests only work on iOS - it looks like the method for parsing the PKCS12 file would need to be ported
#import <Foundation/Foundation.h>
#import <Security/Security.h>
#import "ASITestCase.h"
@interface ClientCertificateTests : ASITestCase {
}
- (void)testClientCertificate;
+ (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data;
@end

View File

@@ -0,0 +1,76 @@
//
// ClientCertificateTests.m
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 18/08/2010.
// Copyright 2010 All-Seeing Interactive. All rights reserved.
//
#import "ClientCertificateTests.h"
#import "ASIHTTPRequest.h"
@implementation ClientCertificateTests
- (void)testClientCertificate
{
// This test will fail the second time it is run, I presume the certificate is being cached somewhere
// This url requires we present a client certificate to connect to it
NSURL *url = [NSURL URLWithString:@"https://clientcertificate.allseeing-i.com:8080/ASIHTTPRequest/tests/first"];
// First, let's attempt to connect to the url without supplying a certificate
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
// We have to turn off validation for these tests, as the server has a self-signed certificate
[request setValidatesSecureCertificate:NO];
[request startSynchronous];
GHAssertNotNil([request error],@"Request succeeded even though we presented no certificate, cannot proceed with test");
// Now, let's grab the certificate (included in the resources of the test app)
SecIdentityRef identity = NULL;
SecTrustRef trust = NULL;
NSData *PKCS12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"client" ofType:@"p12"]];
[ClientCertificateTests extractIdentity:&identity andTrust:&trust fromPKCS12Data:PKCS12Data];
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"https://clientcertificate.allseeing-i.com:8080/ASIHTTPRequest/tests/first"]];
// In this case, we have no need to add extra certificates, just the one inside the indentity will be used
[request setClientCertificateIdentity:identity];
[request setValidatesSecureCertificate:NO];
[request startSynchronous];
// Make sure the request got the correct content
GHAssertNil([request error],@"Request failed with error %@",[request error]);
BOOL success = [[request responseString] isEqualToString:@"This is the expected content for the first string"];
GHAssertTrue(success,@"Request failed to download the correct content");
}
// Based on code from http://developer.apple.com/mac/library/documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks.html
+ (BOOL)extractIdentity:(SecIdentityRef *)outIdentity andTrust:(SecTrustRef*)outTrust fromPKCS12Data:(NSData *)inPKCS12Data
{
OSStatus securityError = errSecSuccess;
NSDictionary *optionsDictionary = [NSDictionary dictionaryWithObject:@"" forKey:(id)kSecImportExportPassphrase];
CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
securityError = SecPKCS12Import((CFDataRef)inPKCS12Data,(CFDictionaryRef)optionsDictionary,&items);
if (securityError == 0) {
CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex (items, 0);
const void *tempIdentity = NULL;
tempIdentity = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemIdentity);
*outIdentity = (SecIdentityRef)tempIdentity;
const void *tempTrust = NULL;
tempTrust = CFDictionaryGetValue (myIdentityAndTrust, kSecImportItemTrust);
*outTrust = (SecTrustRef)tempTrust;
} else {
NSLog(@"Failed with error code %d",(int)securityError);
return NO;
}
return YES;
}
@end

View File

@@ -0,0 +1,89 @@
//
// GHUnitTestMain.m
// GHUnit
//
// Created by Gabriel Handford on 2/22/09.
// Copyright 2009. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
#import <Foundation/Foundation.h>
#import <GHUnit/GHUnit.h>
#import <GHUnit/GHTestApp.h>
#import <GHUnit/GHTesting.h>
// Default exception handler
void exceptionHandler(NSException *exception) {
NSLog(@"%@\n%@", [exception reason], GHUStackTraceFromException(exception));
}
int main(int argc, char *argv[]) {
/*!
For debugging:
Go into the "Get Info" contextual menu of your (test) executable (inside the "Executables" group in the left panel of XCode).
Then go in the "Arguments" tab. You can add the following environment variables:
Default: Set to:
NSDebugEnabled NO "YES"
NSZombieEnabled NO "YES"
NSDeallocateZombies NO "YES"
NSHangOnUncaughtException NO "YES"
NSEnableAutoreleasePool YES "NO"
NSAutoreleaseFreedObjectCheckEnabled NO "YES"
NSAutoreleaseHighWaterMark 0 non-negative integer
NSAutoreleaseHighWaterResolution 0 non-negative integer
For info on these varaiables see NSDebug.h; http://theshadow.uw.hu/iPhoneSDKdoc/Foundation.framework/NSDebug.h.html
For malloc debugging see: http://developer.apple.com/mac/library/documentation/Performance/Conceptual/ManagingMemory/Articles/MallocDebug.html
*/
NSSetUncaughtExceptionHandler(&exceptionHandler);
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Register any special test case classes
//[[GHTesting sharedInstance] registerClassName:@"GHSpecialTestCase"];
int retVal = 0;
// If GHUNIT_CLI is set we are using the command line interface and run the tests
// Otherwise load the GUI app
if (getenv("GHUNIT_CLI")) {
retVal = [GHTestRunner run];
} else {
// To run all tests (from ENV)
GHTestApp *app = [[GHTestApp alloc] init];
// To run a different test suite:
//GHTestSuite *suite = [GHTestSuite suiteWithTestFilter:@"GHSlowTest,GHAsyncTestCaseTest"];
//GHTestApp *app = [[GHTestApp alloc] initWithSuite:suite];
// Or set global:
//GHUnitTest = @"GHSlowTest";
[NSApp run];
[app release];
}
[pool release];
return retVal;
}

View File

@@ -0,0 +1,28 @@
//
// PerformanceTests.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 17/12/2009.
// Copyright 2009 All-Seeing Interactive. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASITestCase.h"
@interface PerformanceTests : ASITestCase {
NSURL *testURL;
NSDate *testStartDate;
int requestsComplete;
NSMutableArray *responseData;
unsigned long bytesDownloaded;
}
- (void)testASIHTTPRequestAsyncPerformance;
- (void)testNSURLConnectionAsyncPerformance;
@property (retain,nonatomic) NSURL *testURL;
@property (retain,nonatomic) NSDate *testStartDate;
@property (assign,nonatomic) int requestsComplete;
@property (retain,nonatomic) NSMutableArray *responseData;
@end

View File

@@ -0,0 +1,234 @@
//
// PerformanceTests.m
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 17/12/2009.
// Copyright 2009 All-Seeing Interactive. All rights reserved.
//
#import "PerformanceTests.h"
#import "ASIHTTPRequest.h"
// IMPORTANT - these tests need to be run one at a time!
@interface NSURLConnectionSubclass : NSURLConnection {
int tag;
}
@property (assign) int tag;
@end
@implementation NSURLConnectionSubclass
@synthesize tag;
@end
// Stop clang complaining about undeclared selectors
@interface PerformanceTests ()
- (void)runSynchronousASIHTTPRequests;
- (void)runSynchronousNSURLConnections;
- (void)startASIHTTPRequests;
- (void)startASIHTTPRequestsWithQueue;
- (void)startNSURLConnections;
@end
@implementation PerformanceTests
- (void)setUp
{
[self setTestURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/the_great_american_novel_%28abridged%29.txt"]];
//[self setTestURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
}
- (void)testASIHTTPRequestSynchronousPerformance
{
[self performSelectorOnMainThread:@selector(runSynchronousASIHTTPRequests) withObject:nil waitUntilDone:YES];
}
- (void)runSynchronousASIHTTPRequests
{
int runTimes = 10;
NSTimeInterval times[runTimes];
int i;
for (i=0; i<runTimes; i++) {
NSDate *startTime = [NSDate date];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:testURL];
//Send the same headers as NSURLRequest
[request addRequestHeader:@"Pragma" value:@"no-cache"];
[request addRequestHeader:@"Accept" value:@"*/*"];
[request addRequestHeader:@"Accept-Language" value:@"en/us"];
[request startSynchronous];
if ([request error]) {
NSLog(@"Request failed - cannot proceed with test");
return;
}
times[i] = [[NSDate date] timeIntervalSinceDate:startTime];
}
NSTimeInterval bestTime = 1000;
NSTimeInterval worstTime = 0;
NSTimeInterval totalTime = 0;
for (i=0; i<runTimes; i++) {
if (times[i] < bestTime) {
bestTime = times[i];
}
if (times[i] > worstTime) {
worstTime = times[i];
}
totalTime += times[i];
}
NSLog(@"Ran %i requests in %f seconds (average time: %f secs / best time: %f secs / worst time: %f secs)",runTimes,totalTime,totalTime/runTimes,bestTime,worstTime);
}
- (void)testNSURLConnectionSynchronousPerformance
{
[self performSelectorOnMainThread:@selector(runSynchronousNSURLConnections) withObject:nil waitUntilDone:YES];
}
- (void)runSynchronousNSURLConnections
{
int runTimes = 10;
NSTimeInterval times[runTimes];
int i;
for (i=0; i<runTimes; i++) {
NSDate *startTime = [NSDate date];
NSURLResponse *response = nil;
NSError *error = nil;
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:testURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (error) {
NSLog(@"Request failed - cannot proceed with test");
return;
}
times[i] = [[NSDate date] timeIntervalSinceDate:startTime];
}
NSTimeInterval bestTime = 1000;
NSTimeInterval worstTime = 0;
NSTimeInterval totalTime = 0;
for (i=0; i<runTimes; i++) {
if (times[i] < bestTime) {
bestTime = times[i];
}
if (times[i] > worstTime) {
worstTime = times[i];
}
totalTime += times[i];
}
NSLog(@"Ran %i requests in %f seconds (average time: %f secs / best time: %f secs / worst time: %f secs)",runTimes,totalTime,totalTime/runTimes,bestTime,worstTime);
}
- (void)testASIHTTPRequestAsyncPerformance
{
[self performSelectorOnMainThread:@selector(startASIHTTPRequests) withObject:nil waitUntilDone:NO];
}
- (void)testQueuedASIHTTPRequestAsyncPerformance
{
[self performSelectorOnMainThread:@selector(startASIHTTPRequestsWithQueue) withObject:nil waitUntilDone:NO];
}
- (void)startASIHTTPRequests
{
bytesDownloaded = 0;
[self setRequestsComplete:0];
[self setTestStartDate:[NSDate date]];
int i;
for (i=0; i<10; i++) {
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:testURL];
//Send the same headers as NSURLRequest
[request addRequestHeader:@"Pragma" value:@"no-cache"];
[request addRequestHeader:@"Accept" value:@"*/*"];
[request addRequestHeader:@"Accept-Language" value:@"en/us"];
[request setDelegate:self];
[request startAsynchronous];
}
}
- (void)startASIHTTPRequestsWithQueue
{
bytesDownloaded = 0;
[self setRequestsComplete:0];
[self setTestStartDate:[NSDate date]];
int i;
NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
[queue setMaxConcurrentOperationCount:4];
for (i=0; i<10; i++) {
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:testURL];
//Send the same headers as NSURLRequest
[request addRequestHeader:@"Pragma" value:@"no-cache"];
[request addRequestHeader:@"Accept" value:@"*/*"];
[request addRequestHeader:@"Accept-Language" value:@"en/us"];
[request setUseCookiePersistence:NO];
[request setUseSessionPersistence:NO];
[request setDelegate:self];
[queue addOperation:request];
}
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
GHFail(@"Cannot proceed with ASIHTTPRequest test - a request failed");
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
bytesDownloaded += [[request responseData] length];
requestsComplete++;
if (requestsComplete == 10) {
NSLog(@"ASIHTTPRequest: Completed 10 (downloaded %lu bytes) requests in %f seconds",bytesDownloaded,[[NSDate date] timeIntervalSinceDate:[self testStartDate]]);
}
}
- (void)testNSURLConnectionAsyncPerformance
{
[self performSelectorOnMainThread:@selector(startNSURLConnections) withObject:nil waitUntilDone:NO];
}
- (void)startNSURLConnections
{
bytesDownloaded = 0;
[self setRequestsComplete:0];
[self setTestStartDate:[NSDate date]];
[self setResponseData:[NSMutableArray arrayWithCapacity:5]];
int i;
for (i=0; i<10; i++) {
NSURLRequest *request = [NSURLRequest requestWithURL:testURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10];
[[self responseData] addObject:[NSMutableData data]];
NSURLConnectionSubclass *connection = [[[NSURLConnectionSubclass alloc] initWithRequest:request delegate:self startImmediately:YES] autorelease];
[connection setTag:i];
}
}
- (void)connection:(NSURLConnectionSubclass *)connection didReceiveResponse:(NSURLResponse *)response
{
}
- (void)connection:(NSURLConnectionSubclass *)connection didFailWithError:(NSError *)error
{
GHFail(@"Cannot proceed with NSURLConnection test - a request failed");
}
- (void)connection:(NSURLConnectionSubclass *)connection didReceiveData:(NSData *)data
{
[[[self responseData] objectAtIndex:[connection tag]] appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnectionSubclass *)connection
{
bytesDownloaded += [[responseData objectAtIndex:[connection tag]] length];
requestsComplete++;
if (requestsComplete == 10) {
NSLog(@"NSURLConnection: Completed 10 (downloaded %lu bytes) requests in %f seconds",bytesDownloaded,[[NSDate date] timeIntervalSinceDate:[self testStartDate]]);
}
}
@synthesize testURL;
@synthesize requestsComplete;
@synthesize testStartDate;
@synthesize responseData;
@end

View File

@@ -0,0 +1,29 @@
//
// ProxyTests.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 02/08/2009.
// Copyright 2009 All-Seeing Interactive. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASITestCase.h"
@class ASINetworkQueue;
// Proxy tests must be run separately from other tests, using the proxy you specify
// Some tests require an authenticating proxy to function
@interface ProxyTests : ASITestCase {
ASINetworkQueue *queue;
BOOL complete;
}
- (void)testProxy;
- (void)testProxyAutodetect;
- (void)testProxyWithSuppliedAuthenticationCredentials;
- (void)testDoubleAuthentication;
- (void)testProxyForHTTPS;
@property (retain) ASINetworkQueue *queue;
@property (assign) BOOL complete;
@end

View File

@@ -0,0 +1,203 @@
//
// ProxyTests.m
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 02/08/2009.
// Copyright 2009 All-Seeing Interactive. All rights reserved.
//
#import "ProxyTests.h"
#import "ASIHTTPRequest.h"
#import "ASINetworkQueue.h"
// Fill in these to run the proxy tests
static NSString *proxyHost = @"";
static int proxyPort = 0;
static NSString *proxyUsername = @"";
static NSString *proxyPassword = @"";
// Stop clang complaining about undeclared selectors
@interface ProxyTests ()
- (void)requestDone:(ASIHTTPRequest *)request;
- (void)requestFailed:(ASIHTTPRequest *)request;
@end
@implementation ProxyTests
- (void)testProxyForHTTPS
{
// Also test we are case-insensitive comparing our scheme
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"HTTPS://selfsigned.allseeing-i.com/"]];
[request setValidatesSecureCertificate:NO];
[request startSynchronous];
BOOL success = ([[request responseString] rangeOfString:@"All-Seeing Interactive"].location != NSNotFound);
GHAssertTrue(success,@"Failed to connect to an HTTPS URL using a proxy");
}
- (void)testAutoConfigureWithPAC
{
NSString *pacurl = @"file:///non-existent.pac";
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setPACurl:[NSURL URLWithString:pacurl]];
[request startSynchronous];
GHAssertNil([request proxyHost],@"Shouldn't use a proxy here");
GHAssertNil([request error],@"Request failed when unable to fetch PAC (should assume no proxy instead)");
// To run this test, specify the location of the pac script that is available at http://developer.apple.com/samplecode/CFProxySupportTool/listing1.html
pacurl = @"file:///Users/ben/Desktop/test.pac";
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setPACurl:[NSURL URLWithString:pacurl]];
[request startSynchronous];
BOOL success = [[request proxyHost] isEqualToString:@"proxy1.apple.com"];
GHAssertTrue(success,@"Failed to use the correct proxy");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com"]];
[request setPACurl:[NSURL URLWithString:pacurl]];
[request startSynchronous];
GHAssertNil([request proxyHost],@"Used a proxy when the script told us to go direct");
}
- (void)testAutoConfigureWithSystemPAC
{
// To run this test, specify the pac script above in your network settings
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request startSynchronous];
BOOL success = [[request proxyHost] isEqualToString:@"proxy1.apple.com"];
GHAssertTrue(success,@"Failed to use the correct proxy");
request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com"]];
[request startSynchronous];
GHAssertNil([request proxyHost],@"Used a proxy when the script told us to go direct");
}
- (void)testProxy
{
BOOL success = (![proxyHost isEqualToString:@""] && proxyPort > 0);
GHAssertTrue(success,@"You need to supply the details of your proxy to run the proxy autodetect test");
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setProxyHost:proxyHost];
[request setProxyPort:proxyPort];
[request startSynchronous];
// Check data is as expected
NSRange notFound = NSMakeRange(NSNotFound, 0);
success = !NSEqualRanges([[request responseString] rangeOfString:@"All-Seeing Interactive"],notFound);
GHAssertTrue(success,@"Failed to download the correct data, navigating the proxy");
}
- (void)testProxyAutodetect
{
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request startSynchronous];
BOOL success = ([request proxyHost] && [request proxyPort]);
GHAssertTrue(success,@"Failed to detect the proxy");
}
- (void)testProxyWithSuppliedAuthenticationCredentials
{
BOOL success = (![proxyHost isEqualToString:@""] && proxyPort > 0 && ![proxyUsername isEqualToString:@""] && ![proxyPassword isEqualToString:@""]);
GHAssertTrue(success,@"You need to supply the details of your authenticating proxy to run the proxy authentication test");
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[request setProxyHost:proxyHost];
[request setProxyPort:proxyPort];
[request setProxyUsername:proxyUsername];
[request setProxyPassword:proxyPassword];
[request startSynchronous];
// Check data is as expected
NSRange notFound = NSMakeRange(NSNotFound, 0);
success = !NSEqualRanges([[request responseString] rangeOfString:@"All-Seeing Interactive"],notFound);
GHAssertTrue(success,@"Failed to download the correct data, navigating the proxy");
}
- (void)testProxyWithDelegateSupplyingCredentials
{
[self setComplete:NO];
BOOL success = (![proxyHost isEqualToString:@""] && proxyPort > 0 && ![proxyUsername isEqualToString:@""] && ![proxyPassword isEqualToString:@""]);
GHAssertTrue(success,@"You need to supply the details of your authenticating proxy to run the proxy authentication test");
[[self queue] cancelAllOperations];
[self setQueue:[ASINetworkQueue queue]];
[[self queue] setDelegate:self];
[[self queue] setRequestDidFinishSelector:@selector(requestFinished:)];
[[self queue] setRequestDidFailSelector:@selector(requestFailed:)];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com"]];
[[self queue] addOperation:request];
[queue go];
while (![self complete]) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
}
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
[self setComplete:YES];
// Check data is as expected
NSRange notFound = NSMakeRange(NSNotFound, 0);
BOOL success = !NSEqualRanges([[request responseString] rangeOfString:@"All-Seeing Interactive"],notFound);
GHAssertTrue(success,@"Failed to download the correct data, navigating the proxy");
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
[self setComplete:YES];
GHAssertTrue(0,@"Request failed when it shouldn't have done so");
}
- (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request
{
[request setProxyUsername:proxyUsername];
[request setProxyPassword:proxyPassword];
[request retryUsingSuppliedCredentials];
}
- (void)testDoubleAuthentication
{
[self setComplete:NO];
BOOL success = (![proxyHost isEqualToString:@""] && proxyPort > 0 && ![proxyUsername isEqualToString:@""] && ![proxyPassword isEqualToString:@""]);
GHAssertTrue(success,@"You need to supply the details of your authenticating proxy to run the proxy authentication test");
[[self queue] cancelAllOperations];
[self setQueue:[ASINetworkQueue queue]];
[[self queue] setDelegate:self];
[[self queue] setRequestDidFinishSelector:@selector(requestDone:)];
[[self queue] setRequestDidFailSelector:@selector(requestFailed:)];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/basic-authentication"]];
[[self queue] addOperation:request];
[queue go];
while (![self complete]) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
}
}
- (void)requestDone:(ASIHTTPRequest *)request
{
[self setComplete:YES];
}
- (void)authenticationNeededForRequest:(ASIHTTPRequest *)request
{
[request setUsername:@"secret_username"];
[request setPassword:@"secret_password"];
[request retryUsingSuppliedCredentials];
}
@synthesize queue;
@synthesize complete;
@end

View File

@@ -0,0 +1,46 @@
//
// StressTests.h
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 30/10/2009.
// Copyright 2009 All-Seeing Interactive. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "ASITestCase.h"
@class ASIHTTPRequest;
@interface MyDelegate : NSObject {
ASIHTTPRequest *request;
}
@property (retain) ASIHTTPRequest *request;
@end
@interface StressTests : ASITestCase {
float progress;
ASIHTTPRequest *cancelRequest;
NSDate *cancelStartDate;
MyDelegate *delegate;
NSLock *createRequestLock;
}
- (void)testCancelQueue;
- (void)testCancelStressTest;
- (void)performCancelRequest;
- (void)testRedirectStressTest;
- (void)performRedirectRequest;
- (void)testSetDelegate;
- (void)performSetDelegateRequest;
- (void)setProgress:(float)newProgress;
@property (retain) ASIHTTPRequest *cancelRequest;
@property (retain) NSDate *cancelStartDate;
@property (retain) MyDelegate *delegate;
@property (retain) NSLock *createRequestLock;
@end

View File

@@ -0,0 +1,192 @@
//
// StressTests.m
// Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest
//
// Created by Ben Copsey on 30/10/2009.
// Copyright 2009 All-Seeing Interactive. All rights reserved.
//
/*
IMPORTANT
All these tests depend on you running a local webserver on port 80
These tests create 1000s of requests in a very short space of time - DO NOT RUN THESE TESTS ON A REMOTE WEBSERVER
IMPORTANT
*/
#import "StressTests.h"
#import "ASIHTTPRequest.h"
#import "ASINetworkQueue.h"
@implementation MyDelegate;
- (void)dealloc
{
[request setDelegate:nil];
[request release];
[super dealloc];
}
@synthesize request;
@end
// Stop clang complaining about undeclared selectors
@interface StressTests ()
- (void)cancelRedirectRequest;
- (void)cancelSetDelegateRequest;
@end
@implementation StressTests
// A test for a potential crasher that used to exist when requests were cancelled
// We aren't testing a specific condition here, but rather attempting to trigger a crash
- (void)testCancelQueue
{
ASINetworkQueue *queue = [ASINetworkQueue queue];
// Increase the risk of this crash
[queue setMaxConcurrentOperationCount:25];
int i;
for (i=0; i<100; i++) {
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1"]];
[queue addOperation:request];
}
[queue go];
[queue cancelAllOperations];
// Run the test again with requests running on a background thread
queue = [ASINetworkQueue queue];
[queue setMaxConcurrentOperationCount:25];
for (i=0; i<100; i++) {
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1"]];
[queue addOperation:request];
}
[queue go];
[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2]];
[queue cancelAllOperations];
}
// This test looks for thread-safety problems with cancelling requests
// It will run for 30 seconds, creating a request, then cancelling it and creating another as soon as it gets some indication of progress
- (void)testCancelStressTest
{
[self setCancelStartDate:[NSDate dateWithTimeIntervalSinceNow:30]];
[self performCancelRequest];
while ([[self cancelStartDate] timeIntervalSinceNow] > 0) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
}
NSLog(@"Stress test: DONE");
}
- (void)performCancelRequest
{
[self setCancelRequest:[ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1/ASIHTTPRequest/tests/the_great_american_novel.txt"]]];
if ([[self cancelStartDate] timeIntervalSinceNow] > 0) {
[[self cancelRequest] setDownloadProgressDelegate:self];
[[self cancelRequest] setShowAccurateProgress:YES];
NSLog(@"Stress test: Start request %@",[self cancelRequest]);
[[self cancelRequest] startAsynchronous];
}
}
// Another stress test that looks from problems when redirecting
- (void)testRedirectStressTest
{
[self setCancelStartDate:[NSDate dateWithTimeIntervalSinceNow:30]];
[self performRedirectRequest];
while ([[self cancelStartDate] timeIntervalSinceNow] > 0) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
}
NSLog(@"Redirect stress test: DONE");
}
- (void)performRedirectRequest
{
[self setCancelRequest:[ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1/ASIHTTPRequest/tests/one_infinite_loop"]]];
if ([[self cancelStartDate] timeIntervalSinceNow] > 0) {
NSLog(@"Redirect stress test: Start request %@",[self cancelRequest]);
[[self cancelRequest] startAsynchronous];
[self performSelector:@selector(cancelRedirectRequest) withObject:nil afterDelay:0.2];
}
}
- (void)cancelRedirectRequest
{
NSLog(@"Redirect stress test: Cancel request %@",[self cancelRequest]);
[[self cancelRequest] cancel];
[self performRedirectRequest];
}
// Ensures we can set the delegate while the request is running without problems
- (void)testSetDelegate
{
[self setCreateRequestLock:[[[NSLock alloc] init] autorelease]];
[self setCancelStartDate:[NSDate dateWithTimeIntervalSinceNow:30]];
[self performSetDelegateRequest];
while ([[self cancelStartDate] timeIntervalSinceNow] > 0) {
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.25]];
}
NSLog(@"Set delegate stress test: DONE");
}
- (void)performSetDelegateRequest
{
[self setDelegate:nil];
[createRequestLock lock];
[self setCancelRequest:[ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://127.0.0.1/ASIHTTPRequest/tests/the_great_american_novel.txt"]]];
if ([[self cancelStartDate] timeIntervalSinceNow] > 0) {
[self setDelegate:[[[MyDelegate alloc] init] autorelease]];
[[self delegate] setRequest:[self cancelRequest]];
[[self cancelRequest] setDelegate:delegate];
[[self cancelRequest] setShowAccurateProgress:YES];
NSLog(@"Set delegate stress test: Start request %@",[self cancelRequest]);
[[self cancelRequest] startAsynchronous];
[self performSelectorInBackground:@selector(cancelSetDelegateRequest) withObject:nil];
}
[createRequestLock unlock];
}
- (void)cancelSetDelegateRequest
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self performSetDelegateRequest];
[pool release];
}
- (void)setDoubleValue:(double)newProgress
{
[self setProgress:(float)newProgress];
}
- (void)setProgress:(float)newProgress
{
progress = newProgress;
// For cancel test
if (newProgress > 0 && [self cancelRequest]) {
NSLog(@"Stress test: Cancel request %@",[self cancelRequest]);
[[self cancelRequest] cancel];
[self performSelector:@selector(performCancelRequest) withObject:nil afterDelay:0.2];
[self setCancelRequest:nil];
}
}
@synthesize cancelRequest;
@synthesize cancelStartDate;
@synthesize delegate;
@synthesize createRequestLock;
@end