aboutsummaryrefslogtreecommitdiff
path: root/Foundation/GTMHTTPFetcherTest.m
diff options
context:
space:
mode:
Diffstat (limited to 'Foundation/GTMHTTPFetcherTest.m')
-rw-r--r--Foundation/GTMHTTPFetcherTest.m516
1 files changed, 0 insertions, 516 deletions
diff --git a/Foundation/GTMHTTPFetcherTest.m b/Foundation/GTMHTTPFetcherTest.m
deleted file mode 100644
index a541d1f..0000000
--- a/Foundation/GTMHTTPFetcherTest.m
+++ /dev/null
@@ -1,516 +0,0 @@
-//
-// GTMHTTPFetcherTest.m
-//
-// Copyright 2007-2008 Google Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License"); you may not
-// use this file except in compliance with the License. You may obtain a copy
-// of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-// License for the specific language governing permissions and limitations under
-// the License.
-//
-
-#import "GTMSenTestCase.h"
-#import "GTMHTTPFetcher.h"
-#import "GTMTestHTTPServer.h"
-#import "GTMUnitTestDevLog.h"
-
-@interface GTMHTTPFetcherTest : GTMTestCase {
- // these ivars are checked after fetches, and are reset by resetFetchResponse
- NSData *fetchedData_;
- NSError *fetcherError_;
- NSInteger fetchedStatus_;
- NSURLResponse *fetchedResponse_;
- NSMutableURLRequest *fetchedRequest_;
-
- // setup/teardown ivars
- NSMutableDictionary *fetchHistory_;
- GTMTestHTTPServer *testServer_;
-}
-@end
-
-@interface GTMHTTPFetcherTest (PrivateMethods)
-- (GTMHTTPFetcher *)doFetchWithURLString:(NSString *)urlString
- cachingDatedData:(BOOL)doCaching;
-
-- (GTMHTTPFetcher *)doFetchWithURLString:(NSString *)urlString
- cachingDatedData:(BOOL)doCaching
- retrySelector:(SEL)retrySel
- maxRetryInterval:(NSTimeInterval)maxRetryInterval
- userData:(id)userData;
-
-- (NSString *)fileURLStringToTestFileName:(NSString *)name;
-- (BOOL)countRetriesFetcher:(GTMHTTPFetcher *)fetcher
- willRetry:(BOOL)suggestedWillRetry
- forError:(NSError *)error;
-- (BOOL)fixRequestFetcher:(GTMHTTPFetcher *)fetcher
- willRetry:(BOOL)suggestedWillRetry
- forError:(NSError *)error;
-- (void)fetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data;
-- (void)fetcher:(GTMHTTPFetcher *)fetcher failedWithError:(NSError *)error;
-@end
-
-@implementation GTMHTTPFetcherTest
-
-static const NSTimeInterval kRunLoopInterval = 0.01;
-// The bogus-fetch test can take >10s to pass. Pick something way higher
-// to avoid failing.
-static const NSTimeInterval kGiveUpInterval = 60.0; // bail on the test if 60 seconds elapse
-
-static NSString *const kValidFileName = @"GTMHTTPFetcherTestPage.html";
-
-- (void)setUp {
- fetchHistory_ = [[NSMutableDictionary alloc] init];
-
- NSBundle *testBundle = [NSBundle bundleForClass:[self class]];
- STAssertNotNil(testBundle, nil);
- NSString *docRoot = [testBundle pathForResource:@"GTMHTTPFetcherTestPage"
- ofType:@"html"];
- docRoot = [docRoot stringByDeletingLastPathComponent];
- STAssertNotNil(docRoot, nil);
-
- testServer_ = [[GTMTestHTTPServer alloc] initWithDocRoot:docRoot];
- STAssertNotNil(testServer_, @"failed to create a testing server");
-}
-
-- (void)resetFetchResponse {
- [fetchedData_ release];
- fetchedData_ = nil;
-
- [fetcherError_ release];
- fetcherError_ = nil;
-
- [fetchedRequest_ release];
- fetchedRequest_ = nil;
-
- [fetchedResponse_ release];
- fetchedResponse_ = nil;
-
- fetchedStatus_ = 0;
-}
-
-- (void)tearDown {
- [testServer_ release];
- testServer_ = nil;
-
- [self resetFetchResponse];
-
- [fetchHistory_ release];
- fetchHistory_ = nil;
-}
-
-- (void)testValidFetch {
- NSString *urlString = [self fileURLStringToTestFileName:kValidFileName];
-
- GTMHTTPFetcher *fetcher =
- [self doFetchWithURLString:urlString cachingDatedData:YES];
-
- STAssertNotNil(fetchedData_,
- @"failed to fetch data, status:%ld error:%@, URL:%@",
- (long)fetchedStatus_, fetcherError_, urlString);
- STAssertNotNil(fetchedResponse_,
- @"failed to get fetch response, status:%ld error:%@",
- (long)fetchedStatus_, fetcherError_);
- STAssertNotNil(fetchedRequest_, @"failed to get fetch request, URL %@",
- urlString);
- STAssertNil(fetcherError_, @"fetching data gave error: %@", fetcherError_);
- STAssertEquals(fetchedStatus_, (NSInteger)200,
- @"fetching data expected status 200, instead got %ld, for URL %@",
- (long)fetchedStatus_, urlString);
-
- // no cookies should be sent with our first request
- NSDictionary *headers = [fetchedRequest_ allHTTPHeaderFields];
- NSString *cookiesSent = [headers objectForKey:@"Cookie"];
- STAssertNil(cookiesSent, @"Cookies sent unexpectedly: %@", cookiesSent);
-
-
- // cookies should have been set by the response; specifically, TestCookie
- // should be set to the name of the file requested
- NSDictionary *responseHeaders;
-
- responseHeaders = [(NSHTTPURLResponse *)fetchedResponse_ allHeaderFields];
- NSString *cookiesSetString = [responseHeaders objectForKey:@"Set-Cookie"];
- NSString *cookieExpected = [NSString stringWithFormat:@"TestCookie=%@",
- kValidFileName];
- STAssertEqualObjects(cookiesSetString, cookieExpected, @"Unexpected cookie");
-
- // test properties
- NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
- @"val1", @"key1", @"val2", @"key2", nil];
- [fetcher setProperties:dict];
- STAssertEqualObjects([fetcher properties], dict, @"properties as dictionary");
- STAssertEqualObjects([fetcher propertyForKey:@"key2"], @"val2",
- @"single property");
-
- NSDictionary *dict2 = [NSDictionary dictionaryWithObjectsAndKeys:
- @"valx1", @"key1", @"val3", @"key3", nil];
- [fetcher setProperty:@"valx1" forKey:@"key1"];
- [fetcher setProperty:nil forKey:@"key2"];
- [fetcher setProperty:@"val3" forKey:@"key3"];
- STAssertEqualObjects([fetcher properties], dict2, @"property changes");
-
- // make a copy of the fetched data to compare with our next fetch from the
- // cache
- NSData *originalFetchedData = [[fetchedData_ copy] autorelease];
-
- // Now fetch again so the "If modified since" header will be set (because
- // we're calling setFetchHistory: below) and caching ON, and verify that we
- // got a good data from the cache, along with a "Not modified" status
-
- [self resetFetchResponse];
-
- [self doFetchWithURLString:urlString cachingDatedData:YES];
-
- STAssertEqualObjects(fetchedData_, originalFetchedData,
- @"cache data mismatch");
-
- STAssertNotNil(fetchedData_,
- @"failed to fetch data, status:%ld error:%@, URL:%@",
- (long)fetchedStatus_, fetcherError_, urlString);
- STAssertNotNil(fetchedResponse_,
- @"failed to get fetch response, status:%;d error:%@",
- (long)fetchedStatus_, fetcherError_);
- STAssertNotNil(fetchedRequest_, @"failed to get fetch request, URL %@",
- urlString);
- STAssertNil(fetcherError_, @"fetching data gave error: %@", fetcherError_);
-
- STAssertEquals(fetchedStatus_, (NSInteger)kGTMHTTPFetcherStatusNotModified, // 304
- @"fetching data expected status 304, instead got %ld, for URL %@",
- (long)fetchedStatus_, urlString);
-
- // the TestCookie set previously should be sent with this request
- cookiesSent = [[fetchedRequest_ allHTTPHeaderFields] objectForKey:@"Cookie"];
- STAssertEqualObjects(cookiesSent, cookieExpected, @"Cookie not sent");
-
- // Now fetch twice without caching enabled, and verify that we got a
- // "Not modified" status, along with a non-nil but empty NSData (which
- // is normal for that status code)
-
- [self resetFetchResponse];
-
- [fetchHistory_ removeAllObjects];
-
- [self doFetchWithURLString:urlString cachingDatedData:NO];
-
- STAssertEqualObjects(fetchedData_, originalFetchedData,
- @"cache data mismatch");
-
- [self resetFetchResponse];
- [self doFetchWithURLString:urlString cachingDatedData:NO];
-
- STAssertNotNil(fetchedData_, @"");
- STAssertEquals([fetchedData_ length], (NSUInteger)0, @"unexpected data");
- STAssertEquals(fetchedStatus_, (NSInteger)kGTMHTTPFetcherStatusNotModified,
- @"fetching data expected status 304, instead got %d", fetchedStatus_);
- STAssertNil(fetcherError_, @"unexpected error: %@", fetcherError_);
-
-}
-
-- (void)testBogusFetch {
- // fetch a live, invalid URL
- NSString *badURLString = @"http://localhost:86/";
- [self doFetchWithURLString:badURLString cachingDatedData:NO];
-
- const int kServiceUnavailableStatus = 503;
-
- if (fetchedStatus_ == kServiceUnavailableStatus) {
- // some proxies give a "service unavailable" error for bogus fetches
- } else {
-
- if (fetchedData_) {
- NSString *str = [[[NSString alloc] initWithData:fetchedData_
- encoding:NSUTF8StringEncoding] autorelease];
- STAssertNil(fetchedData_, @"fetched unexpected data: %@", str);
- }
-
- STAssertNotNil(fetcherError_, @"failed to receive fetching error");
- STAssertEquals(fetchedStatus_, (NSInteger)0,
- @"fetching data expected no status from no response, instead got %d",
- fetchedStatus_);
- }
-
- // fetch with a specific status code from our http server
- [self resetFetchResponse];
-
- NSString *invalidWebPageFile =
- [kValidFileName stringByAppendingString:@"?status=400"];
- NSString *statusUrlString =
- [self fileURLStringToTestFileName:invalidWebPageFile];
-
- [self doFetchWithURLString:statusUrlString cachingDatedData:NO];
-
- STAssertNotNil(fetchedData_, @"fetch lacked data with error info");
- STAssertNil(fetcherError_, @"expected bad status but got an error");
- STAssertEquals(fetchedStatus_, (NSInteger)400,
- @"unexpected status, error=%@", fetcherError_);
-}
-
-- (void)testRetryFetches {
- GTMHTTPFetcher *fetcher;
-
- NSString *invalidFile = [kValidFileName stringByAppendingString:@"?status=503"];
- NSString *urlString = [self fileURLStringToTestFileName:invalidFile];
-
- SEL countRetriesSel = @selector(countRetriesFetcher:willRetry:forError:);
- SEL fixRequestSel = @selector(fixRequestFetcher:willRetry:forError:);
-
- //
- // test: retry until timeout, then expect failure with status message
- //
-
- NSNumber *lotsOfRetriesNumber = [NSNumber numberWithInt:1000];
-
- fetcher= [self doFetchWithURLString:urlString
- cachingDatedData:NO
- retrySelector:countRetriesSel
- maxRetryInterval:5.0 // retry intervals of 1, 2, 4
- userData:lotsOfRetriesNumber];
-
- STAssertNotNil(fetchedData_, @"error data is expected");
- STAssertEquals(fetchedStatus_, (NSInteger)503, nil);
- STAssertEquals([fetcher retryCount], 3U, @"retry count unexpected");
-
- //
- // test: retry twice, then give up
- //
- [self resetFetchResponse];
-
- NSNumber *twoRetriesNumber = [NSNumber numberWithInt:2];
-
- fetcher= [self doFetchWithURLString:urlString
- cachingDatedData:NO
- retrySelector:countRetriesSel
- maxRetryInterval:10.0 // retry intervals of 1, 2, 4, 8
- userData:twoRetriesNumber];
-
- STAssertNotNil(fetchedData_, @"error data is expected");
- STAssertEquals(fetchedStatus_, (NSInteger)503, nil);
- STAssertEquals([fetcher retryCount], 2U, @"retry count unexpected");
-
-
- //
- // test: retry, making the request succeed on the first retry
- // by fixing the URL
- //
- [self resetFetchResponse];
-
- fetcher= [self doFetchWithURLString:urlString
- cachingDatedData:NO
- retrySelector:fixRequestSel
- maxRetryInterval:30.0 // should only retry once due to selector
- userData:lotsOfRetriesNumber];
-
- STAssertNotNil(fetchedData_, @"data is expected");
- STAssertEquals(fetchedStatus_, (NSInteger)200, nil);
- STAssertEquals([fetcher retryCount], 1U, @"retry count unexpected");
-}
-
-- (void)testNilFetch {
- GTMHTTPFetcher *fetcher = [[GTMHTTPFetcher alloc] init];
- [GTMUnitTestDevLog expectString:@"beginFetchWithDelegate requires a request"];
- BOOL wasGood = [fetcher beginFetchWithDelegate:nil
- didFinishSelector:NULL
- didFailSelector:NULL];
- STAssertFalse(wasGood, nil);
-}
-
-- (void)testCookies {
- // This is checking part one of
- // rdar://6293862 NSHTTPCookie cookieWithProperties doesn't work with
- // NSHTTPCookieOriginURL key
- NSString *urlString = @"http://www.apple.com/index.html";
- NSURL *url = [NSURL URLWithString:@"http://www.apple.com/index.html"];
-
- NSDictionary *properties = [NSDictionary dictionaryWithObjectsAndKeys:
- url, NSHTTPCookieOriginURL,
- @"testCookies", NSHTTPCookieName,
- @"1", NSHTTPCookieValue,
- nil];
- NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:properties];
-
- STAssertNil(cookie, nil);
-
- // This is checking part two of
- // rdar://6293862 NSHTTPCookie cookieWithProperties doesn't work with
- // NSHTTPCookieOriginURL key
- properties = [NSDictionary dictionaryWithObjectsAndKeys:
- urlString, NSHTTPCookieOriginURL,
- @"testCookies", NSHTTPCookieName,
- @"1", NSHTTPCookieValue,
- nil];
- cookie = [NSHTTPCookie cookieWithProperties:properties];
-
- STAssertNil(cookie, nil);
-}
-
-#pragma mark -
-
-- (GTMHTTPFetcher *)doFetchWithURLString:(NSString *)urlString
- cachingDatedData:(BOOL)doCaching {
-
- return [self doFetchWithURLString:(NSString *)urlString
- cachingDatedData:(BOOL)doCaching
- retrySelector:nil
- maxRetryInterval:0
- userData:nil];
-}
-
-- (GTMHTTPFetcher *)doFetchWithURLString:(NSString *)urlString
- cachingDatedData:(BOOL)doCaching
- retrySelector:(SEL)retrySel
- maxRetryInterval:(NSTimeInterval)maxRetryInterval
- userData:(id)userData {
-
- NSURL *url = [NSURL URLWithString:urlString];
- NSURLRequest *req = [NSURLRequest requestWithURL:url
- cachePolicy:NSURLRequestReloadIgnoringCacheData
- timeoutInterval:kGiveUpInterval];
- GTMHTTPFetcher *fetcher = [GTMHTTPFetcher httpFetcherWithRequest:req];
-
- STAssertNotNil(fetcher, @"Failed to allocate fetcher");
-
- // setting the fetch history will add the "If-modified-since" header
- // to repeat requests
- [fetcher setFetchHistory:fetchHistory_];
- if (doCaching != [fetcher shouldCacheDatedData]) {
- // only set the value when it changes since setting it to nil clears out
- // some of the state and our tests need the state between some non caching
- // fetches.
- [fetcher setShouldCacheDatedData:doCaching];
- }
-
- if (retrySel) {
- [fetcher setIsRetryEnabled:YES];
- [fetcher setRetrySelector:retrySel];
- [fetcher setMaxRetryInterval:maxRetryInterval];
- [fetcher setUserData:userData];
-
- // we force a minimum retry interval for unit testing; otherwise,
- // we'd have no idea how many retries will occur before the max
- // retry interval occurs, since the minimum would be random
- [fetcher setMinRetryInterval:1.0];
- }
-
- BOOL isFetching =
- [fetcher beginFetchWithDelegate:self
- didFinishSelector:@selector(fetcher:finishedWithData:)
- didFailSelector:@selector(fetcher:failedWithError:)];
- STAssertTrue(isFetching, @"Begin fetch failed");
-
- if (isFetching) {
-
- // Give time for the fetch to happen, but give up if 10 seconds elapse with
- // no response
- NSDate* giveUpDate = [NSDate dateWithTimeIntervalSinceNow:kGiveUpInterval];
- while ((!fetchedData_ && !fetcherError_) &&
- [giveUpDate timeIntervalSinceNow] > 0) {
- NSDate* loopIntervalDate =
- [NSDate dateWithTimeIntervalSinceNow:kRunLoopInterval];
- [[NSRunLoop currentRunLoop] runUntilDate:loopIntervalDate];
- }
- }
-
- return fetcher;
-}
-
-- (NSString *)fileURLStringToTestFileName:(NSString *)name {
-
- // we need to create http URLs referring to the desired
- // resource to be found by the python http server running locally
-
- // return a localhost:port URL for the test file
- NSString *urlString = [NSString stringWithFormat:@"http://localhost:%d/%@",
- [testServer_ port], name];
-
- // we exclude the "?status=" that would indicate that the URL
- // should cause a retryable error
- NSRange range = [name rangeOfString:@"?status="];
- if (range.length > 0) {
- name = [name substringToIndex:range.location];
- }
-
- // we exclude the ".auth" extension that would indicate that the URL
- // should be tested with authentication
- if ([[name pathExtension] isEqual:@"auth"]) {
- name = [name stringByDeletingPathExtension];
- }
-
- // just for sanity, let's make sure we see the file locally, so
- // we can expect the Python http server to find it too
- NSBundle *testBundle = [NSBundle bundleForClass:[self class]];
- STAssertNotNil(testBundle, nil);
-
- NSString *filePath =
- [testBundle pathForResource:[name stringByDeletingPathExtension]
- ofType:[name pathExtension]];
- STAssertNotNil(filePath, nil);
-
- return urlString;
-}
-
-
-
-- (void)fetcher:(GTMHTTPFetcher *)fetcher finishedWithData:(NSData *)data {
- fetchedData_ = [data copy];
- fetchedStatus_ = [fetcher statusCode]; // this implicitly tests that the fetcher has kept the response
- fetchedRequest_ = [[fetcher request] retain];
- fetchedResponse_ = [[fetcher response] retain];
-}
-
-- (void)fetcher:(GTMHTTPFetcher *)fetcher failedWithError:(NSError *)error {
- // if it's a status error, don't hang onto the error, just the status/data
- if ([[error domain] isEqual:kGTMHTTPFetcherStatusDomain]) {
- fetchedData_ = [[[error userInfo] objectForKey:kGTMHTTPFetcherStatusDataKey] copy];
- fetchedStatus_ = [error code]; // this implicitly tests that the fetcher has kept the response
- } else {
- fetcherError_ = [error retain];
- fetchedStatus_ = [fetcher statusCode];
- }
-}
-
-
-// Selector for allowing up to N retries, where N is an NSNumber in the
-// fetcher's userData
-- (BOOL)countRetriesFetcher:(GTMHTTPFetcher *)fetcher
- willRetry:(BOOL)suggestedWillRetry
- forError:(NSError *)error {
-
- int count = [fetcher retryCount];
- int allowedRetryCount = [[fetcher userData] intValue];
-
- BOOL shouldRetry = (count < allowedRetryCount);
-
- STAssertEquals([fetcher nextRetryInterval], pow(2.0, [fetcher retryCount]),
- @"unexpected next retry interval (expected %f, was %f)",
- pow(2.0, [fetcher retryCount]),
- [fetcher nextRetryInterval]);
-
- return shouldRetry;
-}
-
-// Selector for retrying and changing the request to one that will succeed
-- (BOOL)fixRequestFetcher:(GTMHTTPFetcher *)fetcher
- willRetry:(BOOL)suggestedWillRetry
- forError:(NSError *)error {
-
- STAssertEquals([fetcher nextRetryInterval], pow(2.0, [fetcher retryCount]),
- @"unexpected next retry interval (expected %f, was %f)",
- pow(2.0, [fetcher retryCount]),
- [fetcher nextRetryInterval]);
-
- // fix it - change the request to a URL which does not have a status value
- NSString *urlString = [self fileURLStringToTestFileName:kValidFileName];
-
- NSURL *url = [NSURL URLWithString:urlString];
- [fetcher setRequest:[NSURLRequest requestWithURL:url]];
-
- return YES; // do the retry fetch; it should succeed now
-}
-
-@end