// Copyright 2019 Google // // 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 "FirebaseStorage/Sources/FIRStorageListTask.h" #import "FirebaseStorage/Tests/Unit/FIRStorageTestHelpers.h" @interface FIRStorageListTests : XCTestCase @property(strong, nonatomic) GTMSessionFetcherService *fetcherService; @property(nonatomic) dispatch_queue_t dispatchQueue; @property(strong, nonatomic) FIRStorage *storage; @property(strong, nonatomic) id mockApp; @end @implementation FIRStorageListTests - (void)setUp { [super setUp]; id mockOptions = OCMClassMock([FIROptions class]); OCMStub([mockOptions storageBucket]).andReturn(@"bucket.appspot.com"); self.mockApp = [FIRStorageTestHelpers mockedApp]; OCMStub([self.mockApp name]).andReturn(kFIRStorageAppName); OCMStub([(FIRApp *)self.mockApp options]).andReturn(mockOptions); self.fetcherService = [[GTMSessionFetcherService alloc] init]; self.fetcherService.authorizer = [[FIRStorageTokenAuthorizer alloc] initWithGoogleAppID:@"dummyAppID" fetcherService:self.fetcherService authProvider:nil]; self.dispatchQueue = dispatch_queue_create("Test dispatch queue", DISPATCH_QUEUE_SERIAL); self.storage = [FIRStorage storageForApp:self.mockApp]; } - (void)tearDown { self.fetcherService = nil; self.storage = nil; self.mockApp = nil; [super tearDown]; } - (void)testValidatesInput { XCTestExpectation *expectation = [self expectationWithDescription:@"testValidatesInput"]; expectation.expectedFulfillmentCount = 4; FIRStoragePath *path = [FIRStorageTestHelpers objectPath]; FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path]; FIRStorageVoidListError errorBlock = ^(FIRStorageListResult *result, NSError *error) { XCTAssertNil(result); XCTAssertNotNil(error); XCTAssertEqualObjects(error.domain, @"FIRStorageErrorDomain"); XCTAssertEqual(error.code, FIRStorageErrorCodeInvalidArgument); [expectation fulfill]; }; [ref listWithMaxResults:0 completion:errorBlock]; [ref listWithMaxResults:1001 completion:errorBlock]; [ref listWithMaxResults:0 pageToken:@"foo" completion:errorBlock]; [ref listWithMaxResults:1001 pageToken:@"foo" completion:errorBlock]; [FIRStorageTestHelpers waitForExpectation:self]; } - (void)testListAllCallbackOnlyCalledOnce { XCTestExpectation *expectation = [self expectationWithDescription:@"testListAllCallbackOnlyCalledOnce"]; expectation.expectedFulfillmentCount = 1; FIRStoragePath *path = [FIRStorageTestHelpers objectPath]; FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path]; FIRStorageVoidListError errorBlock = ^(FIRStorageListResult *result, NSError *error) { XCTAssertNil(result); XCTAssertNotNil(error); XCTAssertEqualObjects(error.domain, @"FIRStorageErrorDomain"); XCTAssertEqual(error.code, FIRStorageErrorCodeUnknown); [expectation fulfill]; }; [ref listAllWithCompletion:errorBlock]; [FIRStorageTestHelpers waitForExpectation:self]; } - (void)testDefaultList { XCTestExpectation *expectation = [self expectationWithDescription:@"testDefaultList"]; NSURL *expectedURL = [NSURL URLWithString: @"https://firebasestorage.googleapis.com/v0/b/bucket/o?prefix=object/&delimiter=/"]; self.fetcherService.testBlock = ^(GTMSessionFetcher *fetcher, GTMSessionFetcherTestResponse response) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-retain-cycles" XCTAssertEqualObjects(fetcher.request.URL, expectedURL); // Implicitly retains self XCTAssertEqualObjects(fetcher.request.HTTPMethod, @"GET"); #pragma clang diagnostic pop NSHTTPURLResponse *httpResponse = [[NSHTTPURLResponse alloc] initWithURL:fetcher.request.URL statusCode:200 HTTPVersion:kHTTPVersion headerFields:nil]; response(httpResponse, nil, nil); }; FIRStoragePath *path = [FIRStorageTestHelpers objectPath]; FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path]; FIRStorageListTask *task = [[FIRStorageListTask alloc] initWithReference:ref fetcherService:self.fetcherService dispatchQueue:self.dispatchQueue pageSize:nil previousPageToken:nil completion:^(FIRStorageListResult *result, NSError *error) { [expectation fulfill]; }]; [task enqueue]; [FIRStorageTestHelpers waitForExpectation:self]; } - (void)testListWithPageSizeAndPageToken { XCTestExpectation *expectation = [self expectationWithDescription:@"testListWithPageSizeAndPageToken"]; NSURL *expectedURL = [NSURL URLWithString:@"https://firebasestorage.googleapis.com/v0/b/bucket/" @"o?maxResults=42&delimiter=/&prefix=object/&pageToken=foo"]; self.fetcherService.testBlock = ^(GTMSessionFetcher *fetcher, GTMSessionFetcherTestResponse response) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-retain-cycles" XCTAssertEqualObjects(fetcher.request.URL, expectedURL); // Implicitly retains self XCTAssertEqualObjects(fetcher.request.HTTPMethod, @"GET"); #pragma clang diagnostic pop NSHTTPURLResponse *httpResponse = [[NSHTTPURLResponse alloc] initWithURL:fetcher.request.URL statusCode:200 HTTPVersion:kHTTPVersion headerFields:nil]; response(httpResponse, nil, nil); }; FIRStoragePath *path = [FIRStorageTestHelpers objectPath]; FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path]; FIRStorageListTask *task = [[FIRStorageListTask alloc] initWithReference:ref fetcherService:self.fetcherService dispatchQueue:self.dispatchQueue pageSize:@(42) previousPageToken:@"foo" completion:^(FIRStorageListResult *result, NSError *error) { [expectation fulfill]; }]; [task enqueue]; [FIRStorageTestHelpers waitForExpectation:self]; } - (void)testPercentEncodesPlusToken { XCTestExpectation *expectation = [self expectationWithDescription:@"testPercentEncodesPlusToken"]; NSURL *expectedURL = [NSURL URLWithString:@"https://firebasestorage.googleapis.com/v0/b/bucket/" @"o?prefix=%2Bfoo/&delimiter=/"]; self.fetcherService.testBlock = ^(GTMSessionFetcher *fetcher, GTMSessionFetcherTestResponse response) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Warc-retain-cycles" XCTAssertEqualObjects(fetcher.request.URL, expectedURL); // Implicitly retains self XCTAssertEqualObjects(fetcher.request.HTTPMethod, @"GET"); #pragma clang diagnostic pop NSHTTPURLResponse *httpResponse = [[NSHTTPURLResponse alloc] initWithURL:fetcher.request.URL statusCode:200 HTTPVersion:kHTTPVersion headerFields:nil]; response(httpResponse, nil, nil); }; FIRStoragePath *path = [FIRStoragePath pathFromString:@"https://firebasestorage.googleapis.com/v0/b/bucket/0/+foo"]; FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path]; FIRStorageListTask *task = [[FIRStorageListTask alloc] initWithReference:ref fetcherService:self.fetcherService dispatchQueue:self.dispatchQueue pageSize:nil previousPageToken:nil completion:^(FIRStorageListResult *result, NSError *error) { [expectation fulfill]; }]; [task enqueue]; [FIRStorageTestHelpers waitForExpectation:self]; } - (void)testListWithResponse { XCTestExpectation *expectation = [self expectationWithDescription:@"testListWithErrorResponse"]; NSString *jsonString = @"{\n" " \"prefixes\": [\n" " \"object/prefixWithoutSlash\",\n" " \"object/prefixWithSlash/\"\n" " ],\n" " \"items\": [\n" " {\n" " \"name\": \"object/data1.dat\",\n" " \"bucket\": \"bucket.appspot.com\"\n" " },\n" " {\n" " \"name\": \"object/data2.dat\",\n" " \"bucket\": \"bucket.appspot.com\"\n" " },\n" " ],\n" " \"nextPageToken\": \"foo\"" "}"; NSData *responseData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; self.fetcherService.testBlock = ^(GTMSessionFetcher *fetcher, GTMSessionFetcherTestResponse response) { NSHTTPURLResponse *httpResponse = [[NSHTTPURLResponse alloc] initWithURL:fetcher.request.URL statusCode:200 HTTPVersion:kHTTPVersion headerFields:nil]; response(httpResponse, responseData, nil); }; FIRStoragePath *path = [FIRStorageTestHelpers objectPath]; FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path]; FIRStorageListTask *task = [[FIRStorageListTask alloc] initWithReference:ref fetcherService:self.fetcherService dispatchQueue:self.dispatchQueue pageSize:nil previousPageToken:nil completion:^(FIRStorageListResult *result, NSError *error) { XCTAssertNotNil(result); XCTAssertNil(error); XCTAssertEqualObjects(result.items, (@[ [ref child:@"data1.dat"], [ref child:@"data2.dat"] ])); XCTAssertEqualObjects( result.prefixes, (@[ [ref child:@"prefixWithoutSlash"], [ref child:@"prefixWithSlash"] // The slash has been trimmed. ])); XCTAssertEqualObjects(result.pageToken, @"foo"); [expectation fulfill]; }]; [task enqueue]; [FIRStorageTestHelpers waitForExpectation:self]; } - (void)testListWithErrorResponse { XCTestExpectation *expectation = [self expectationWithDescription:@"testListWithErrorResponse"]; NSError *error = [NSError errorWithDomain:@"com.google.firebase.storage" code:404 userInfo:nil]; self.fetcherService.testBlock = ^(GTMSessionFetcher *fetcher, GTMSessionFetcherTestResponse response) { NSHTTPURLResponse *httpResponse = [[NSHTTPURLResponse alloc] initWithURL:fetcher.request.URL statusCode:403 HTTPVersion:kHTTPVersion headerFields:nil]; response(httpResponse, nil, error); }; FIRStoragePath *path = [FIRStorageTestHelpers objectPath]; FIRStorageReference *ref = [[FIRStorageReference alloc] initWithStorage:self.storage path:path]; FIRStorageListTask *task = [[FIRStorageListTask alloc] initWithReference:ref fetcherService:self.fetcherService dispatchQueue:self.dispatchQueue pageSize:nil previousPageToken:nil completion:^(FIRStorageListResult *result, NSError *error) { XCTAssertNotNil(error); XCTAssertNil(result); XCTAssertEqualObjects(error.domain, @"FIRStorageErrorDomain"); XCTAssertEqual(error.code, FIRStorageErrorCodeObjectNotFound); [expectation fulfill]; }]; [task enqueue]; [FIRStorageTestHelpers waitForExpectation:self]; } @end