/core/externals/update-engine/externals/gdata-objectivec-client/Source/HTTPFetcher/Tests/GTMHTTPFetcherServiceTest.m
http://macfuse.googlecode.com/ · Objective C · 316 lines · 212 code · 59 blank · 45 comment · 19 complexity · 185e37054bdf93a13df3cee4290ff44b MD5 · raw file
- /* Copyright (c) 2011 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 <XCTest/XCTest.h>
- #import "GTMHTTPFetcherTestServer.h"
- #import "GTMHTTPFetcherService.h"
- @interface GTMHTTPFetcherServiceTest : XCTestCase {
- GTMHTTPFetcherTestServer *testServer_;
- BOOL isServerRunning_;
- }
- @end
- @implementation GTMHTTPFetcherServiceTest
- // file available in Tests folder
- static NSString *const kValidFileName = @"gettysburgaddress.txt";
- - (NSString *)docRootPath {
- // find a test file
- NSBundle *testBundle = [NSBundle bundleForClass:[self class]];
- XCTAssertNotNil(testBundle);
- // use the directory of the test file as the root directory for our server
- NSString *docFolder = [testBundle resourcePath];
- return docFolder;
- }
- - (void)setUp {
- NSString *docRoot = [self docRootPath];
- testServer_ = [[GTMHTTPFetcherTestServer alloc] initWithDocRoot:docRoot];
- isServerRunning_ = (testServer_ != nil);
- XCTAssertTrue(isServerRunning_,
- @">>> http test server failed to launch; skipping"
- " service tests\n");
- }
- - (void)tearDown {
- [testServer_ release];
- testServer_ = nil;
- isServerRunning_ = NO;
- }
- - (void)testFetcherService {
- if (!isServerRunning_) return;
- // Utility blocks for counting array entries for a specific host
- NSUInteger (^URLsPerHost) (NSArray *, NSString *) = ^(NSArray *URLs,
- NSString *host) {
- NSUInteger counter = 0;
- for (NSURL *url in URLs) {
- if ([host isEqual:[url host]]) counter++;
- }
- return counter;
- };
-
- NSUInteger (^FetchersPerHost) (NSArray *, NSString *) = ^(NSArray *fetchers,
- NSString *host) {
- NSArray *fetcherURLs = [fetchers valueForKeyPath:@"mutableRequest.URL"];
- return URLsPerHost(fetcherURLs, host);
- };
- // Utility block for finding the minimum priority fetcher for a specific host
- NSInteger (^PriorityPerHost) (NSArray *, NSString *) = ^(NSArray *fetchers,
- NSString *host) {
- NSInteger val = NSIntegerMax;
- for (GTMHTTPFetcher *fetcher in fetchers) {
- if ([host isEqual:[[fetcher.mutableRequest URL] host]]) {
- val = MIN(val, fetcher.servicePriority);
- }
- }
- return val;
- };
- // We'll verify we fetched from the server the same data that is on disk
- NSString *gettysburgPath = [testServer_ localPathForFile:kValidFileName];
- NSData *gettysburgAddress = [NSData dataWithContentsOfFile:gettysburgPath];
- NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
- // We'll create 10 fetchers. Only 2 should run simultaneously.
- // 1 should fail; the rest should succeeed.
- const NSUInteger kMaxRunningFetchersPerHost = 2;
- NSString *const kUserAgent = @"ServiceTest-UA";
- const NSTimeInterval kTimeout = 55;
- GTMHTTPFetcherService *service = [[[GTMHTTPFetcherService alloc] init] autorelease];
- service.maxRunningFetchersPerHost = kMaxRunningFetchersPerHost;
- service.fetchHistory.shouldRememberETags = NO;
- service.userAgent = kUserAgent;
- service.timeout = kTimeout;
- // Make URLs for a valid fetch, a fetch that returns a status error,
- // and a valid fetch with a different host
- NSURL *validFileURL = [testServer_ localURLForFile:kValidFileName];
- NSString *invalidFile = [kValidFileName stringByAppendingString:@"?status=400"];
- NSURL *invalidFileURL = [testServer_ localURLForFile:invalidFile];
- NSString *validURLStr = [validFileURL absoluteString];
- NSString *altValidURLStr = [validURLStr stringByReplacingOccurrencesOfString:@"localhost"
- withString:@"127.0.0.1"];
- NSURL *altValidURL = [NSURL URLWithString:altValidURLStr];
- XCTAssertEqualObjects([validFileURL host], @"localhost", @"unexpected host");
- XCTAssertEqualObjects([invalidFileURL host], @"localhost", @"unexpected host");
- XCTAssertEqualObjects([altValidURL host], @"127.0.0.1", @"unexpected host");
- // Make an array with the urls from the different hosts, including one
- // that will fail with a status 400 error
- NSMutableArray *urlArray = [NSMutableArray array];
- for (int idx = 1; idx <= 4; idx++) [urlArray addObject:validFileURL];
- [urlArray addObject:invalidFileURL];
- for (int idx = 1; idx <= 5; idx++) [urlArray addObject:validFileURL];
- for (int idx = 1; idx <= 5; idx++) [urlArray addObject:altValidURL];
- for (int idx = 1; idx <= 5; idx++) [urlArray addObject:validFileURL];
- NSUInteger totalNumberOfFetchers = [urlArray count];
- __block NSMutableArray *pending = [NSMutableArray array];
- __block NSMutableArray *running = [NSMutableArray array];
- __block NSMutableArray *completed = [NSMutableArray array];
- NSUInteger priorityVal = 0;
- // Create all the fetchers
- for (NSURL *fileURL in urlArray) {
- GTMHTTPFetcher *fetcher = [service fetcherWithURL:fileURL];
- // Fetcher start notification
- [nc addObserverForName:kGTMHTTPFetcherStartedNotification
- object:fetcher
- queue:nil
- usingBlock:^(NSNotification *note) {
- // Verify that we have at most two fetchers running for this
- // fetcher's host
- [running addObject:fetcher];
- [pending removeObject:fetcher];
- NSMutableURLRequest *fetcherReq = [fetcher mutableRequest];
- NSURL *fetcherReqURL = [fetcherReq URL];
- NSString *host = [fetcherReqURL host];
- NSUInteger numberRunning = FetchersPerHost(running, host);
- XCTAssertTrue(numberRunning > 0, @"count error");
- XCTAssertTrue(numberRunning <= kMaxRunningFetchersPerHost,
- @"too many running");
- NSInteger pendingPriority = PriorityPerHost(pending, host);
- XCTAssertTrue(fetcher.servicePriority <= pendingPriority,
- @"a pending fetcher has greater priority");
- XCTAssertEqual([service numberOfFetchers],
- [running count] + [pending count],
- @"fetcher count off");
- XCTAssertEqual([service numberOfRunningFetchers],
- [running count], @"running off");
- XCTAssertEqual([service numberOfDelayedFetchers],
- [pending count], @"delayed off");
- NSArray *matches =
- [service issuedFetchersWithRequestURL:fetcherReqURL];
- NSUInteger idx = NSNotFound;
- if (matches) {
- idx = [matches indexOfObjectIdenticalTo:fetcher];
- }
- XCTAssertTrue(idx != NSNotFound, @"Missing %@ in %@",
- fetcherReqURL, matches);
- NSURL *fakeURL =
- [NSURL URLWithString:@"http://example.com/bad"];
- matches = [service issuedFetchersWithRequestURL:fakeURL];
- XCTAssertEqual([matches count], (NSUInteger)0);
- NSString *agent = [fetcherReq valueForHTTPHeaderField:@"User-Agent"];
- XCTAssertEqualObjects(agent, kUserAgent);
- XCTAssertEqual([fetcherReq timeoutInterval], kTimeout);
- }];
- // Fetcher stopped notification
- [nc addObserverForName:kGTMHTTPFetcherStoppedNotification
- object:fetcher
- queue:nil
- usingBlock:^(NSNotification *note) {
- // Verify that we only have two fetchers running
- [completed addObject:fetcher];
- [running removeObject:fetcher];
- NSString *host = [[[fetcher mutableRequest] URL] host];
- NSUInteger numberRunning = FetchersPerHost(running, host);
- NSUInteger numberPending = FetchersPerHost(pending, host);
- NSUInteger numberCompleted = FetchersPerHost(completed, host);
- XCTAssertTrue(numberRunning <= kMaxRunningFetchersPerHost,
- @"too many running");
- XCTAssertTrue(numberPending + numberRunning + numberCompleted <= URLsPerHost(urlArray, host),
- @"%d issued running (pending:%u running:%u completed:%u)",
- (unsigned int)totalNumberOfFetchers, (unsigned int)numberPending,
- (unsigned int)numberRunning, (unsigned int)numberCompleted);
- XCTAssertEqual([service numberOfFetchers],
- [running count] + [pending count] + 1,
- @"fetcher count off");
- XCTAssertEqual([service numberOfRunningFetchers],
- [running count] + 1, @"running off");
- XCTAssertEqual([service numberOfDelayedFetchers],
- [pending count], @"delayed off");
- }];
- [pending addObject:fetcher];
- // Set the fetch priority to a value that cycles 0, 1, -1, 0, ...
- priorityVal++;
- if (priorityVal > 1) priorityVal = -1;
- fetcher.servicePriority = priorityVal;
- // Start this fetcher
- [fetcher beginFetchWithCompletionHandler:^(NSData *fetchData, NSError *fetchError) {
- // Callback
- //
- // The query should be empty except for the URL with a status code
- NSString *query = [[[fetcher mutableRequest] URL] query];
- BOOL isValidRequest = ([query length] == 0);
- if (isValidRequest) {
- XCTAssertEqualObjects(fetchData, gettysburgAddress,
- @"Bad fetch data");
- XCTAssertNil(fetchError, @"unexpected %@ %@",
- fetchError, [fetchError userInfo]);
- } else {
- // This is the query with ?status=400
- XCTAssertEqual([fetchError code], (NSInteger) 400, @"expected error");
- }
- }];
- }
- [service waitForCompletionOfAllFetchersWithTimeout:10];
- XCTAssertEqual([pending count], (NSUInteger) 0,
- @"still pending: %@", pending);
- XCTAssertEqual([running count], (NSUInteger) 0,
- @"still running: %@", running);
- XCTAssertEqual([completed count], (NSUInteger) totalNumberOfFetchers,
- @"incomplete");
- XCTAssertEqual([service numberOfFetchers], (NSUInteger) 0,
- @"service non-empty");
- }
- - (void)testStopAllFetchers {
- if (!isServerRunning_) return;
- GTMHTTPFetcherService *service = [[[GTMHTTPFetcherService alloc] init] autorelease];
- service.maxRunningFetchersPerHost = 2;
- service.fetchHistory.shouldRememberETags = NO;
- // Create three fetchers for each of two URLs, so there should be
- // two running and one delayed for each
- NSURL *validFileURL = [testServer_ localURLForFile:kValidFileName];
- NSString *validURLStr = [validFileURL absoluteString];
- NSString *altValidURLStr = [validURLStr stringByReplacingOccurrencesOfString:@"localhost"
- withString:@"127.0.0.1"];
- NSURL *altValidURL = [NSURL URLWithString:altValidURLStr];
- // Add three fetches for each URL
- NSMutableArray *urlArray = [NSMutableArray array];
- [urlArray addObject:validFileURL];
- [urlArray addObject:altValidURL];
- [urlArray addObject:validFileURL];
- [urlArray addObject:altValidURL];
- [urlArray addObject:validFileURL];
- [urlArray addObject:altValidURL];
- // Create and start all the fetchers
- for (NSURL *fileURL in urlArray) {
- GTMHTTPFetcher *fetcher = [service fetcherWithURL:fileURL];
- [fetcher beginFetchWithCompletionHandler:^(NSData *fetchData, NSError *fetchError) {
- // We shouldn't reach any of the callbacks
- XCTFail(@"Fetcher completed but should have been stopped");
- }];
- }
- // Two hosts
- XCTAssertEqual([service.runningHosts count], (NSUInteger)2, @"hosts running");
- XCTAssertEqual([service.delayedHosts count], (NSUInteger)2, @"hosts delayed");
- // We should see two fetchers running and one delayed for each host
- NSArray *localhosts = [service.runningHosts objectForKey:@"localhost"];
- XCTAssertEqual([localhosts count], (NSUInteger)2, @"hosts running");
- localhosts = [service.delayedHosts objectForKey:@"localhost"];
- XCTAssertEqual([localhosts count], (NSUInteger)1, @"hosts delayed");
- [service stopAllFetchers];
- XCTAssertEqual([service.runningHosts count], (NSUInteger)0, @"hosts running");
- XCTAssertEqual([service.delayedHosts count], (NSUInteger)0, @"hosts delayed");
- }
- @end