Files
firebase-ios-sdk/FirebaseStorage/Tests/Unit/StorageReferenceTests.swift
T

292 lines
10 KiB
Swift

// Copyright 2022 Google LLC
//
// 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 Foundation
import FirebaseCore
@testable import FirebaseStorage
import FirebaseAppCheckInterop
import FirebaseAuthInterop
import SharedTestUtilities
import XCTest
class StorageReferenceTests: XCTestCase {
override class func setUp() {
let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
gcmSenderID: "00000000000000000-00000000000-000000000")
options.projectID = "myProjectID-Ref"
FirebaseApp.configure(name: "test-StorageReference", options: options)
}
var storage: Storage?
override func setUp() {
guard let app = try? getApp(bucket: "bucket") else {
fatalError("")
}
storage = Storage.storage(app: app)
}
func testRoot() throws {
let ref = storage!.reference(forURL: "gs://bucket/path/to/object")
XCTAssertEqual(ref.root().description, "gs://bucket/")
}
func testRootWithURLAPI() throws {
let url = try XCTUnwrap(URL(string: "gs://bucket/path/to/object"))
let ref = try storage!.reference(for: url)
XCTAssertEqual(ref.root().description, "gs://bucket/")
}
func testRootWithNoPath() throws {
let ref = storage!.reference(forURL: "gs://bucket/")
XCTAssertEqual(ref.root().description, "gs://bucket/")
}
func testMismatchedBucket() throws {
do {
let url = try XCTUnwrap(URL(string: "gs://bcket/"))
_ = try storage!.reference(for: url)
} catch let StorageError.bucketMismatch(string) {
XCTAssertEqual(string, "Provided bucket: `bcket` does not match the Storage " +
"bucket of the current instance: `bucket`")
return
}
XCTFail()
}
func testMismatchedBucket2() throws {
let url = try XCTUnwrap(URL(string: "gs://bcket/"))
XCTAssertThrowsError(try storage!.reference(for: url), "This was supposed to fail.") { error in
XCTAssertEqual(
"\(error)",
"bucketMismatch(\"Provided bucket: `bcket` does not match the Storage " +
"bucket of the current instance: `bucket`\")"
)
}
}
func testBadBucketScheme() throws {
do {
let url = try XCTUnwrap(URL(string: "htttp://bucket/"))
_ = try storage!.reference(for: url)
} catch let StorageError.pathError(string) {
XCTAssertEqual(
string,
"Internal error: URL scheme must be one of gs://, http://, or https://"
)
return
}
XCTFail()
}
func testBadBucketScheme2() throws {
let url = try XCTUnwrap(URL(string: "htttp://bucket/"))
XCTAssertThrowsError(try storage!.reference(for: url), "This was supposed to fail.") { error in
XCTAssertEqual("\(error)", "pathError(\"Internal error: URL scheme must be one of gs://, " +
"http://, or https://\")")
}
}
func testSingleChild() throws {
let ref = storage!.reference(forURL: "gs://bucket/")
let childRef = ref.child("path")
XCTAssertEqual(childRef.description, "gs://bucket/path")
}
func testMultipleChildrenSingleString() throws {
let ref = storage!.reference(forURL: "gs://bucket/")
let childRef = ref.child("path/to/object")
XCTAssertEqual(childRef.description, "gs://bucket/path/to/object")
}
func testMultipleChildrenMultipleStrings() throws {
let ref = storage!.reference(forURL: "gs://bucket/")
let childRef = ref.child("path").child("to").child("object")
XCTAssertEqual(childRef.description, "gs://bucket/path/to/object")
}
func testSameChildDifferentRef() throws {
let ref = storage!.reference(forURL: "gs://bucket/")
let firstRef = ref.child("1")
let secondRef = ref.child("1")
XCTAssertEqual(ref.description, "gs://bucket/")
XCTAssertTrue(firstRef == secondRef)
XCTAssertFalse(firstRef === secondRef)
}
func testDifferentChildDifferentRef() throws {
let ref = storage!.reference(forURL: "gs://bucket/")
let firstRef = ref.child("1")
let secondRef = ref.child("2")
XCTAssertEqual(ref.description, "gs://bucket/")
XCTAssertFalse(firstRef == secondRef)
XCTAssertFalse(firstRef === secondRef)
}
func testChildWithTrailingSlash() throws {
let ref = storage!.reference(forURL: "gs://bucket/path/to/object/")
XCTAssertEqual(ref.description, "gs://bucket/path/to/object")
}
func testChildWithLeadingSlash() throws {
let ref = storage!.reference(forURL: "gs://bucket//path/to/object/")
XCTAssertEqual(ref.description, "gs://bucket/path/to/object")
}
func testChildCompressSlashes() throws {
let ref = storage!.reference(forURL: "gs://bucket//path/////to////object////")
XCTAssertEqual(ref.description, "gs://bucket/path/to/object")
}
func testParent() throws {
let ref = storage!.reference(forURL: "gs://bucket//path/to/object/")
let parentRef = try XCTUnwrap(ref.parent())
XCTAssertEqual(parentRef.description, "gs://bucket/path/to")
}
func testParentToRoot() throws {
let ref = storage!.reference(forURL: "gs://bucket/path")
let parentRef = try XCTUnwrap(ref.parent())
XCTAssertEqual(parentRef.description, "gs://bucket/")
}
func testParentToRootTrailingSlash() throws {
let ref = storage!.reference(forURL: "gs://bucket/path/")
let parentRef = try XCTUnwrap(ref.parent())
XCTAssertEqual(parentRef.description, "gs://bucket/")
}
func testParentAtRoot() throws {
let ref = storage!.reference(forURL: "gs://bucket/")
XCTAssertNil(ref.parent())
}
func testBucket() throws {
let ref = storage!.reference(forURL: "gs://bucket//path/to/object/")
XCTAssertEqual(ref.bucket, "bucket")
}
func testName() throws {
let ref = storage!.reference(forURL: "gs://bucket/path/to/object/")
XCTAssertEqual(ref.name, "object")
}
func testNameNoObject() throws {
let ref = storage!.reference(forURL: "gs://bucket/")
XCTAssertEqual(ref.name, "")
}
func testFullPath() throws {
let ref = storage!.reference(forURL: "gs://bucket/path/to/object/")
XCTAssertEqual(ref.fullPath, "path/to/object")
}
func testFullPathNoObject() throws {
let ref = storage!.reference(forURL: "gs://bucket/")
XCTAssertEqual(ref.fullPath, "")
}
func testCopy() throws {
let ref = storage!.reference(forURL: "gs://bucket/")
let copiedRef = ref.copy() as? StorageReference
XCTAssertTrue(ref == copiedRef)
XCTAssertFalse(ref === copiedRef)
}
func testReferenceWithNonExistentFileFailsWithCompletionResult() throws {
let tempFilePath = NSTemporaryDirectory().appending("temp.data")
let ref = storage!.reference(withPath: tempFilePath)
let dummyFileURL = try XCTUnwrap(URL(string: "some_non_existing-folder/file.data"))
let expectation = self.expectation(description: #function)
ref.putFile(from: dummyFileURL) { result in
expectation.fulfill()
switch result {
case .success:
XCTFail("Unexpected success.", file: #file, line: #line)
case let .failure(error):
switch error {
case let StorageError.unknown(message):
let expectedDescription = "File at URL: \(dummyFileURL.absoluteString) " +
"is not reachable. Ensure file URL is not a directory, symbolic link, or invalid url."
XCTAssertEqual(expectedDescription, message)
default:
XCTFail("Failed to match expected Internal Error")
}
}
}
waitForExpectations(timeout: 0.5)
}
func testReferenceWithNonExistentFileFailsWithCompletionCallback() throws {
let tempFilePath = NSTemporaryDirectory().appending("temp.data")
let ref = storage!.reference(withPath: tempFilePath)
let dummyFileURL = try XCTUnwrap(URL(string: "some_non_existing-folder/file.data"))
let expectation = self.expectation(description: #function)
ref.putFile(from: dummyFileURL) { metadata, error in
expectation.fulfill()
XCTAssertNil(metadata)
let nsError = (error as? NSError)!
XCTAssertEqual(nsError.code, StorageErrorCode.unknown.rawValue)
let expectedDescription = "File at URL: \(dummyFileURL.absoluteString) " +
"is not reachable. Ensure file URL is not a directory, symbolic link, or invalid url."
XCTAssertEqual(expectedDescription, nsError.localizedDescription)
XCTAssertEqual(nsError.domain, StorageErrorDomain)
}
waitForExpectations(timeout: 0.5)
}
func testReferenceWithNilFileFailsWithCompletionCallback() throws {
let tempFilePath = NSTemporaryDirectory().appending("temp.data")
let ref = storage!.reference(withPath: tempFilePath)
let dummyFileURL = try XCTUnwrap(URL(string: "bad-url"))
let expectation = self.expectation(description: #function)
ref.putFile(from: dummyFileURL) { metadata, error in
expectation.fulfill()
XCTAssertNil(metadata)
let nsError = (error as? NSError)!
XCTAssertEqual(nsError.code, StorageErrorCode.unknown.rawValue)
let expectedDescription = "File at URL: \(dummyFileURL.absoluteString) " +
"is not reachable. Ensure file URL is not a directory, symbolic link, or invalid url."
XCTAssertEqual(expectedDescription, nsError.localizedDescription)
XCTAssertEqual(nsError.domain, StorageErrorDomain)
}
waitForExpectations(timeout: 1.0)
}
// MARK: Private Helpers
// Cache the app associated with each Storage bucket
private static var appDictionary: [String: FirebaseApp] = [:]
private func getApp(bucket: String) throws -> FirebaseApp {
let savedApp = StorageReferenceTests.appDictionary[bucket]
guard savedApp == nil else {
return try XCTUnwrap(savedApp)
}
let options = FirebaseOptions(googleAppID: "0:0000000000000:ios:0000000000000000",
gcmSenderID: "00000000000000000-00000000000-000000000")
options.projectID = "myProjectID"
options.storageBucket = bucket
let name = "StorageTests\(bucket)"
let app = FirebaseApp(instanceWithName: name, options: options)
StorageReferenceTests.appDictionary[bucket] = app
return app
}
}