| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| |
| let kURLTestParsingTestsKey = "ParsingTests" |
| |
| let kURLTestTitleKey = "In-Title" |
| let kURLTestUrlKey = "In-Url" |
| let kURLTestBaseKey = "In-Base" |
| let kURLTestURLCreatorKey = "In-URLCreator" |
| let kURLTestPathComponentKey = "In-PathComponent" |
| let kURLTestPathExtensionKey = "In-PathExtension" |
| |
| let kURLTestCFResultsKey = "Out-CFResults" |
| let kURLTestNSResultsKey = "Out-NSResults" |
| |
| let kNSURLWithStringCreator = "NSURLWithString" |
| let kCFURLCreateWithStringCreator = "CFURLCreateWithString" |
| let kCFURLCreateWithBytesCreator = "CFURLCreateWithBytes" |
| let kCFURLCreateAbsoluteURLWithBytesCreator = "CFURLCreateAbsoluteURLWithBytes" |
| |
| let kNullURLString = "<null url>" |
| let kNullString = "<null>" |
| |
| /// Reads the test data plist file and returns the list of objects |
| private func getTestData() -> [Any]? { |
| let testFilePath = testBundle().url(forResource: "NSURLTestData", withExtension: "plist") |
| let data = try! Data(contentsOf: testFilePath!) |
| guard let plist = try? PropertyListSerialization.propertyList(from: data, options: [], format: nil) else { |
| XCTFail("Unable to deserialize property list data") |
| return nil |
| } |
| guard let testRoot = plist as? [String : Any] else { |
| XCTFail("Unable to deserialize property list data") |
| return nil |
| } |
| guard let parsingTests = testRoot[kURLTestParsingTestsKey] as? [Any] else { |
| XCTFail("Unable to create the parsingTests dictionary") |
| return nil |
| } |
| return parsingTests |
| } |
| |
| class TestURL : XCTestCase { |
| #if os(Windows) |
| func test_WindowsPathSeparator() { |
| // ensure that the mixed slashes are handled properly |
| // e.g. NOT file:///S:/b/u1%2/ |
| let u1 = URL(fileURLWithPath: "S:\\b\\u1/") |
| XCTAssertEqual(u1.absoluteString, "file:///S:/b/u1/") |
| |
| // ensure that trailing slashes are compressed |
| // e.g. NOT file:///S:/b/u2%2F%2F%2F%/ |
| let u2 = URL(fileURLWithPath: "S:\\b\\u2/////") |
| XCTAssertEqual(u2.absoluteString, "file:///S:/b/u2/") |
| |
| // ensure that the trailing slashes are compressed even when mixed |
| // e.g. NOT file:///S:/b/u3%2F%/%2F%2/ |
| let u3 = URL(fileURLWithPath: "S:\\b\\u3//\\//") |
| // XCTAssertEqual(u3.absoluteString, "file:///S:/b/u3/%2F/") |
| XCTAssertEqual(u3.path, "S:\\b\\u3\\") |
| |
| // ensure that the regular conversion works |
| let u4 = URL(fileURLWithPath: "S:\\b\\u4") |
| XCTAssertEqual(u4.absoluteString, "file:///S:/b/u4") |
| |
| // ensure that the trailing slash is added |
| let u5 = URL(fileURLWithPath: "S:\\b\\u5", isDirectory: true) |
| XCTAssertEqual(u5.absoluteString, "file:///S:/b/u5/") |
| |
| // ensure that the trailing slash is preserved |
| let u6 = URL(fileURLWithPath: "S:\\b\\u6\\") |
| XCTAssertEqual(u6.absoluteString, "file:///S:/b/u6/") |
| |
| // ensure that we do not index beyond the start of the string |
| let u7 = URL(fileURLWithPath: "eh", relativeTo: URL(fileURLWithPath: "S:\\b")) |
| XCTAssertEqual(u7.absoluteString, "file:///S:/b/eh") |
| |
| // ensure that / is handled properly |
| let u8 = URL(fileURLWithPath: "/") |
| XCTAssertEqual(u8.absoluteString, "file:///") |
| } |
| |
| func test_WindowsPathSeparator2() { |
| let u1 = URL(fileURLWithPath: "S:\\b\\u1\\", isDirectory: false) |
| XCTAssertEqual(u1.absoluteString, "file:///S:/b/u1") |
| |
| let u2 = URL(fileURLWithPath: "/", isDirectory: false) |
| XCTAssertEqual(u2.absoluteString, "file:///") |
| |
| let u3 = URL(fileURLWithPath: "\\", isDirectory: false) |
| XCTAssertEqual(u3.absoluteString, "file:///") |
| |
| let u4 = URL(fileURLWithPath: "S:\\b\\u3//\\//") |
| XCTAssertEqual(u4.absoluteString, "file:///S:/b/u3/") |
| } |
| #endif |
| |
| func test_fileURLWithPath_relativeTo() { |
| let homeDirectory = NSHomeDirectory() |
| let homeURL = URL(fileURLWithPath: homeDirectory, isDirectory: true) |
| XCTAssertEqual(homeDirectory, homeURL.path) |
| |
| #if os(macOS) |
| let baseURL = URL(fileURLWithPath: homeDirectory, isDirectory: true) |
| let relativePath = "Documents" |
| #elseif os(Android) |
| let baseURL = URL(fileURLWithPath: "/data", isDirectory: true) |
| let relativePath = "local" |
| #elseif os(Linux) |
| let baseURL = URL(fileURLWithPath: "/usr", isDirectory: true) |
| let relativePath = "include" |
| #elseif os(Windows) |
| let baseURL = URL(fileURLWithPath: homeDirectory, isDirectory: true) |
| let relativePath = "Documents" |
| #endif |
| // we're telling fileURLWithPath:isDirectory:relativeTo: Documents is a directory |
| let url1 = URL(fileURLWithFileSystemRepresentation: relativePath, isDirectory: true, relativeTo: baseURL) |
| // we're letting fileURLWithPath:relativeTo: determine Documents is a directory with I/O |
| let url2 = URL(fileURLWithPath: relativePath, relativeTo: baseURL) |
| XCTAssertEqual(url1, url2, "\(url1) was not equal to \(url2)") |
| // we're telling fileURLWithPath:relativeTo: Documents is a directory with a trailing slash |
| let url3 = URL(fileURLWithPath: relativePath + "/", relativeTo: baseURL) |
| XCTAssertEqual(url1, url3, "\(url1) was not equal to \(url3)") |
| } |
| |
| /// Returns a URL from the given url string and base |
| private func URLWithString(_ urlString : String, baseString : String?) -> URL? { |
| if let baseString = baseString { |
| let baseURL = URL(string: baseString) |
| return URL(string: urlString, relativeTo: baseURL) |
| } else { |
| return URL(string: urlString) |
| } |
| } |
| |
| internal func generateResults(_ url: URL, pathComponent: String?, pathExtension : String?) -> [String : Any] { |
| var result = [String : Any]() |
| if let pathComponent = pathComponent { |
| let newFileURL = url.appendingPathComponent(pathComponent, isDirectory: false) |
| result["appendingPathComponent-File"] = newFileURL.relativeString |
| result["appendingPathComponent-File-BaseURL"] = newFileURL.baseURL?.relativeString ?? kNullString |
| |
| let newDirURL = url.appendingPathComponent(pathComponent, isDirectory: true) |
| result["appendingPathComponent-Directory"] = newDirURL.relativeString |
| result["appendingPathComponent-Directory-BaseURL"] = newDirURL.baseURL?.relativeString ?? kNullString |
| } else if let pathExtension = pathExtension { |
| let newURL = url.appendingPathExtension(pathExtension) |
| result["appendingPathExtension"] = newURL.relativeString |
| result["appendingPathExtension-BaseURL"] = newURL.baseURL?.relativeString ?? kNullString |
| } else { |
| result["relativeString"] = url.relativeString |
| result["baseURLString"] = url.baseURL?.relativeString ?? kNullString |
| result["absoluteString"] = url.absoluteString |
| result["absoluteURLString"] = url.absoluteURL.relativeString |
| result["scheme"] = url.scheme ?? kNullString |
| result["host"] = url.host ?? kNullString |
| |
| result["port"] = url.port ?? kNullString |
| result["user"] = url.user ?? kNullString |
| result["password"] = url.password ?? kNullString |
| result["path"] = url.path |
| result["query"] = url.query ?? kNullString |
| result["fragment"] = url.fragment ?? kNullString |
| result["relativePath"] = url.relativePath |
| result["isFileURL"] = url.isFileURL ? "YES" : "NO" |
| result["standardizedURL"] = url.standardized.relativeString |
| |
| result["pathComponents"] = url.pathComponents |
| result["lastPathComponent"] = url.lastPathComponent |
| result["pathExtension"] = url.pathExtension |
| result["deletingLastPathComponent"] = url.deletingLastPathComponent().relativeString |
| result["deletingLastPathExtension"] = url.deletingPathExtension().relativeString |
| } |
| return result |
| } |
| |
| internal func compareResults(_ url : URL, expected : [String : Any], got : [String : Any]) -> (Bool, [String]) { |
| var differences = [String]() |
| for (key, obj) in expected { |
| // Skip non-string expected results |
| if ["port", "standardizedURL", "pathComponents"].contains(key) { |
| continue |
| } |
| if let expectedValue = obj as? String { |
| if let testedValue = got[key] as? String { |
| if expectedValue != testedValue { |
| differences.append(" \(key) Expected = '\(expectedValue)', Got = '\(testedValue)'") |
| } |
| } else { |
| differences.append(" \(key) Expected = '\(expectedValue)', Got = '\(String(describing: got[key]))'") |
| } |
| } else if let expectedValue = obj as? [String] { |
| if let testedValue = got[key] as? [String] { |
| if expectedValue != testedValue { |
| differences.append(" \(key) Expected = '\(expectedValue)', Got = '\(testedValue)'") |
| } |
| } else { |
| differences.append(" \(key) Expected = '\(expectedValue)', Got = '\(String(describing: got[key]))'") |
| } |
| } else if let expectedValue = obj as? Int { |
| if let testedValue = got[key] as? Int { |
| if expectedValue != testedValue { |
| differences.append(" \(key) Expected = '\(expectedValue)', Got = '\(testedValue)'") |
| } |
| } else { |
| differences.append(" \(key) Expected = '\(expectedValue)', Got = '\(String(describing: got[key]))'") |
| } |
| } |
| |
| } |
| for (key, obj) in got { |
| if expected[key] == nil { |
| differences.append(" \(key) Expected = 'nil', Got = '\(obj)'") |
| } |
| } |
| if differences.count > 0 { |
| differences.sort() |
| differences.insert(" url: '\(url)' ", at: 0) |
| return (false, differences) |
| } else { |
| return (true, []) |
| } |
| } |
| |
| func test_URLStrings() { |
| for obj in getTestData()! { |
| let testDict = obj as! [String: Any] |
| let title = testDict[kURLTestTitleKey] as! String |
| let inURL = testDict[kURLTestUrlKey]! as! String |
| let inBase = testDict[kURLTestBaseKey] as! String? |
| let inPathComponent = testDict[kURLTestPathComponentKey] as! String? |
| let inPathExtension = testDict[kURLTestPathExtensionKey] as! String? |
| let expectedNSResult = testDict[kURLTestNSResultsKey]! |
| var url : URL? = nil |
| |
| switch (testDict[kURLTestURLCreatorKey]! as! String) { |
| case kNSURLWithStringCreator: |
| url = URLWithString(inURL, baseString: inBase) |
| case kCFURLCreateWithStringCreator, kCFURLCreateWithBytesCreator, kCFURLCreateAbsoluteURLWithBytesCreator: |
| // TODO: Not supported right now |
| continue |
| default: |
| XCTFail() |
| } |
| if title == "NSURLWithString-parse-ambiguous-url-001" { |
| // TODO: Fix this test |
| } else { |
| if let url = url { |
| let results = generateResults(url, pathComponent: inPathComponent, pathExtension: inPathExtension) |
| if let expected = expectedNSResult as? [String: Any] { |
| let (isEqual, differences) = compareResults(url, expected: expected, got: results) |
| XCTAssertTrue(isEqual, "\(title): \(differences.joined(separator: "\n"))") |
| } else { |
| XCTFail("\(url) should not be a valid url") |
| } |
| } else { |
| XCTAssertEqual(expectedNSResult as? String, kNullURLString) |
| } |
| } |
| } |
| |
| } |
| |
| static let gBaseTemporaryDirectoryPath = (NSTemporaryDirectory() as NSString).appendingPathComponent("org.swift.foundation.TestFoundation.TestURL.\(ProcessInfo.processInfo.processIdentifier)") |
| static var gBaseCurrentWorkingDirectoryPath : String { |
| return FileManager.default.currentDirectoryPath |
| } |
| static var gRelativeOffsetFromBaseCurrentWorkingDirectory: UInt = 0 |
| static let gFileExistsName = "TestCFURL_file_exists\(ProcessInfo.processInfo.globallyUniqueString)" |
| static let gFileDoesNotExistName = "TestCFURL_file_does_not_exist" |
| static let gDirectoryExistsName = "TestCFURL_directory_exists\(ProcessInfo.processInfo.globallyUniqueString)" |
| static let gDirectoryDoesNotExistName = "TestCFURL_directory_does_not_exist" |
| static let gFileExistsPath = gBaseTemporaryDirectoryPath + gFileExistsName |
| static let gFileDoesNotExistPath = gBaseTemporaryDirectoryPath + gFileDoesNotExistName |
| static let gDirectoryExistsPath = gBaseTemporaryDirectoryPath + gDirectoryExistsName |
| static let gDirectoryDoesNotExistPath = gBaseTemporaryDirectoryPath + gDirectoryDoesNotExistName |
| |
| override class func tearDown() { |
| let path = TestURL.gBaseTemporaryDirectoryPath |
| if (try? FileManager.default.attributesOfItem(atPath: path)) != nil { |
| do { |
| try FileManager.default.removeItem(atPath: path) |
| } catch { |
| NSLog("Could not remove test directory at path \(path): \(error)") |
| } |
| } |
| |
| super.tearDown() |
| } |
| |
| static func setup_test_paths() -> Bool { |
| _ = FileManager.default.createFile(atPath: gFileExistsPath, contents: nil) |
| |
| do { |
| try FileManager.default.removeItem(atPath: gFileDoesNotExistPath) |
| } catch { |
| // The error code is a CocoaError |
| if (error as? NSError)?.code != CocoaError.fileNoSuchFile.rawValue { |
| return false |
| } |
| } |
| |
| do { |
| try FileManager.default.createDirectory(atPath: gDirectoryExistsPath, withIntermediateDirectories: false) |
| } catch { |
| // The error code is a CocoaError |
| if (error as? NSError)?.code != CocoaError.fileWriteFileExists.rawValue { |
| return false |
| } |
| } |
| |
| do { |
| try FileManager.default.removeItem(atPath: gDirectoryDoesNotExistPath) |
| } catch { |
| // The error code is a CocoaError |
| if (error as? NSError)?.code != CocoaError.fileNoSuchFile.rawValue { |
| return false |
| } |
| } |
| |
| #if os(Android) |
| FileManager.default.changeCurrentDirectoryPath("/data/local/tmp") |
| #endif |
| |
| let cwd = FileManager.default.currentDirectoryPath |
| let cwdURL = URL(fileURLWithPath: cwd, isDirectory: true) |
| // 1 for path separator |
| cwdURL.withUnsafeFileSystemRepresentation { |
| gRelativeOffsetFromBaseCurrentWorkingDirectory = UInt(strlen($0!) + 1) |
| } |
| |
| return true |
| } |
| |
| func test_fileURLWithPath() { |
| if !TestURL.setup_test_paths() { |
| let error = strerror(errno)! |
| XCTFail("Failed to set up test paths: \(String(cString: error))") |
| } |
| |
| // test with file that exists |
| var path = TestURL.gFileExistsPath |
| var url = NSURL(fileURLWithPath: path) |
| XCTAssertFalse(url.hasDirectoryPath, "did not expect URL with directory path: \(url)") |
| XCTAssertEqual(path, url.path, "path from file path URL is wrong") |
| |
| // test with file that doesn't exist |
| path = TestURL.gFileDoesNotExistPath |
| url = NSURL(fileURLWithPath: path) |
| XCTAssertFalse(url.hasDirectoryPath, "did not expect URL with directory path: \(url)") |
| XCTAssertEqual(path, url.path, "path from file path URL is wrong") |
| |
| // test with directory that exists |
| path = TestURL.gDirectoryExistsPath |
| url = NSURL(fileURLWithPath: path) |
| XCTAssertTrue(url.hasDirectoryPath, "expected URL with directory path: \(url)") |
| XCTAssertEqual(path, url.path, "path from file path URL is wrong") |
| |
| // test with directory that doesn't exist |
| path = TestURL.gDirectoryDoesNotExistPath |
| url = NSURL(fileURLWithPath: path) |
| XCTAssertFalse(url.hasDirectoryPath, "did not expect URL with directory path: \(url)") |
| XCTAssertEqual(path, url.path, "path from file path URL is wrong") |
| |
| // test with name relative to current working directory |
| path = TestURL.gFileDoesNotExistName |
| url = NSURL(fileURLWithPath: path) |
| XCTAssertFalse(url.hasDirectoryPath, "did not expect URL with directory path: \(url)") |
| let fileSystemRep = url.fileSystemRepresentation |
| let actualLength = strlen(fileSystemRep) |
| // 1 for path separator |
| let expectedLength = UInt(strlen(TestURL.gFileDoesNotExistName)) + TestURL.gRelativeOffsetFromBaseCurrentWorkingDirectory |
| XCTAssertEqual(UInt(actualLength), expectedLength, "fileSystemRepresentation was too short") |
| XCTAssertTrue(strncmp(TestURL.gBaseCurrentWorkingDirectoryPath, fileSystemRep, Int(strlen(TestURL.gBaseCurrentWorkingDirectoryPath))) == 0, "fileSystemRepresentation of base path is wrong") |
| let lengthOfRelativePath = Int(strlen(TestURL.gFileDoesNotExistName)) |
| let relativePath = fileSystemRep.advanced(by: Int(TestURL.gRelativeOffsetFromBaseCurrentWorkingDirectory)) |
| XCTAssertTrue(strncmp(TestURL.gFileDoesNotExistName, relativePath, lengthOfRelativePath) == 0, "fileSystemRepresentation of file path is wrong") |
| } |
| |
| func test_fileURLWithPath_isDirectory() { |
| if !TestURL.setup_test_paths() { |
| let error = strerror(errno)! |
| XCTFail("Failed to set up test paths: \(String(cString: error))") |
| } |
| |
| // test with file that exists |
| var path = TestURL.gFileExistsPath |
| var url = NSURL(fileURLWithPath: path, isDirectory: true) |
| XCTAssertTrue(url.hasDirectoryPath, "expected URL with directory path: \(url)") |
| url = NSURL(fileURLWithPath: path, isDirectory: false) |
| XCTAssertFalse(url.hasDirectoryPath, "did not expect URL with directory path: \(url)") |
| XCTAssertEqual(path, url.path, "path from file path URL is wrong") |
| |
| // test with file that doesn't exist |
| path = TestURL.gFileDoesNotExistPath |
| url = NSURL(fileURLWithPath: path, isDirectory: true) |
| XCTAssertTrue(url.hasDirectoryPath, "expected URL with directory path: \(url)") |
| url = NSURL(fileURLWithPath: path, isDirectory: false) |
| XCTAssertFalse(url.hasDirectoryPath, "did not expect URL with directory path: \(url)") |
| XCTAssertEqual(path, url.path, "path from file path URL is wrong") |
| |
| // test with directory that exists |
| path = TestURL.gDirectoryExistsPath |
| url = NSURL(fileURLWithPath: path, isDirectory: false) |
| XCTAssertFalse(url.hasDirectoryPath, "did not expect URL with directory path: \(url)") |
| url = NSURL(fileURLWithPath: path, isDirectory: true) |
| XCTAssertTrue(url.hasDirectoryPath, "expected URL with directory path: \(url)") |
| XCTAssertEqual(path, url.path, "path from file path URL is wrong") |
| |
| // test with directory that doesn't exist |
| path = TestURL.gDirectoryDoesNotExistPath |
| url = NSURL(fileURLWithPath: path, isDirectory: false) |
| XCTAssertFalse(url.hasDirectoryPath, "did not expect URL with directory path: \(url)") |
| url = NSURL(fileURLWithPath: path, isDirectory: true) |
| XCTAssertTrue(url.hasDirectoryPath, "expected URL with directory path: \(url)") |
| XCTAssertEqual(path, url.path, "path from file path URL is wrong") |
| |
| // test with name relative to current working directory |
| path = TestURL.gFileDoesNotExistName |
| url = NSURL(fileURLWithPath: path, isDirectory: false) |
| XCTAssertFalse(url.hasDirectoryPath, "did not expect URL with directory path: \(url)") |
| url = NSURL(fileURLWithPath: path, isDirectory: true) |
| XCTAssertTrue(url.hasDirectoryPath, "expected URL with directory path: \(url)") |
| let fileSystemRep = url.fileSystemRepresentation |
| let actualLength = UInt(strlen(fileSystemRep)) |
| // 1 for path separator |
| let expectedLength = UInt(strlen(TestURL.gFileDoesNotExistName)) + TestURL.gRelativeOffsetFromBaseCurrentWorkingDirectory |
| XCTAssertEqual(actualLength, expectedLength, "fileSystemRepresentation was too short") |
| XCTAssertTrue(strncmp(TestURL.gBaseCurrentWorkingDirectoryPath, fileSystemRep, Int(strlen(TestURL.gBaseCurrentWorkingDirectoryPath))) == 0, "fileSystemRepresentation of base path is wrong") |
| let lengthOfRelativePath = Int(strlen(TestURL.gFileDoesNotExistName)) |
| let relativePath = fileSystemRep.advanced(by: Int(TestURL.gRelativeOffsetFromBaseCurrentWorkingDirectory)) |
| XCTAssertTrue(strncmp(TestURL.gFileDoesNotExistName, relativePath, lengthOfRelativePath) == 0, "fileSystemRepresentation of file path is wrong") |
| } |
| |
| func test_URLByResolvingSymlinksInPath() { |
| let files = [ |
| NSTemporaryDirectory() + "ABC/test_URLByResolvingSymlinksInPath" |
| ] |
| |
| guard ensureFiles(files) else { |
| XCTAssert(false, "Could create files for testing.") |
| return |
| } |
| |
| // tmp is special because it is symlinked to /private/tmp and this /private prefix should be dropped, |
| // so tmp is tmp. On Linux tmp is not symlinked so it would be the same. |
| do { |
| let url = URL(fileURLWithPath: "/.//tmp/ABC/..") |
| let result = url.resolvingSymlinksInPath().absoluteString |
| XCTAssertEqual(result, "file:///tmp/", "URLByResolvingSymlinksInPath removes extraneous path components and resolve symlinks.") |
| } |
| |
| do { |
| let url = URL(fileURLWithPath: "~") |
| let result = url.resolvingSymlinksInPath().absoluteString |
| let expected = "file://" + FileManager.default.currentDirectoryPath + "/~" |
| XCTAssertEqual(result, expected, "URLByResolvingSymlinksInPath resolves relative paths using current working directory.") |
| } |
| |
| do { |
| let url = URL(fileURLWithPath: "anysite.com/search") |
| let result = url.resolvingSymlinksInPath().absoluteString |
| let expected = "file://" + FileManager.default.currentDirectoryPath + "/anysite.com/search" |
| XCTAssertEqual(result, expected) |
| } |
| |
| // tmp is symlinked on macOS only |
| #if os(macOS) |
| do { |
| let url = URL(fileURLWithPath: "/tmp/..") |
| let result = url.resolvingSymlinksInPath().absoluteString |
| XCTAssertEqual(result, "file:///private/") |
| } |
| #else |
| do { |
| let url = URL(fileURLWithPath: "/tmp/ABC/test_URLByResolvingSymlinksInPath") |
| let result = url.resolvingSymlinksInPath().absoluteString |
| XCTAssertEqual(result, "file:///tmp/ABC/test_URLByResolvingSymlinksInPath", "URLByResolvingSymlinksInPath appends trailing slash for existing directories only") |
| } |
| #endif |
| |
| do { |
| let url = URL(fileURLWithPath: "/tmp/ABC/..") |
| let result = url.resolvingSymlinksInPath().absoluteString |
| XCTAssertEqual(result, "file:///tmp/") |
| } |
| } |
| |
| func test_reachable() { |
| #if os(Android) |
| var url = URL(fileURLWithPath: "/data") |
| #elseif os(Windows) |
| var url = URL(fileURLWithPath: NSHomeDirectory()) |
| #else |
| var url = URL(fileURLWithPath: "/usr") |
| #endif |
| XCTAssertEqual(true, try? url.checkResourceIsReachable()) |
| |
| url = URL(string: "https://www.swift.org")! |
| do { |
| _ = try url.checkResourceIsReachable() |
| XCTFail() |
| } catch let error as NSError { |
| XCTAssertEqual(NSCocoaErrorDomain, error.domain) |
| XCTAssertEqual(CocoaError.Code.fileReadUnsupportedScheme.rawValue, error.code) |
| } catch { |
| XCTFail() |
| } |
| |
| url = URL(fileURLWithPath: "/some_random_path") |
| do { |
| _ = try url.checkResourceIsReachable() |
| XCTFail() |
| } catch let error as NSError { |
| XCTAssertEqual(NSCocoaErrorDomain, error.domain) |
| XCTAssertEqual(CocoaError.Code.fileReadNoSuchFile.rawValue, error.code) |
| } catch { |
| XCTFail() |
| } |
| |
| #if os(Android) |
| var nsURL = NSURL(fileURLWithPath: "/data") |
| #elseif os(Windows) |
| var nsURL = NSURL(fileURLWithPath: NSHomeDirectory()) |
| #else |
| var nsURL = NSURL(fileURLWithPath: "/usr") |
| #endif |
| XCTAssertEqual(true, try? nsURL.checkResourceIsReachable()) |
| |
| nsURL = NSURL(string: "https://www.swift.org")! |
| do { |
| _ = try nsURL.checkResourceIsReachable() |
| XCTFail() |
| } catch let error as NSError { |
| XCTAssertEqual(NSCocoaErrorDomain, error.domain) |
| XCTAssertEqual(CocoaError.Code.fileReadUnsupportedScheme.rawValue, error.code) |
| } catch { |
| XCTFail() |
| } |
| |
| nsURL = NSURL(fileURLWithPath: "/some_random_path") |
| do { |
| _ = try nsURL.checkResourceIsReachable() |
| XCTFail() |
| } catch let error as NSError { |
| XCTAssertEqual(NSCocoaErrorDomain, error.domain) |
| XCTAssertEqual(CocoaError.Code.fileReadNoSuchFile.rawValue, error.code) |
| } catch { |
| XCTFail() |
| } |
| } |
| |
| func test_copy() { |
| let url = NSURL(string: "https://www.swift.org") |
| let urlCopy = url!.copy() as! NSURL |
| XCTAssertTrue(url!.isEqual(urlCopy)) |
| |
| let queryItem = NSURLQueryItem(name: "id", value: "23") |
| let queryItemCopy = queryItem.copy() as! NSURLQueryItem |
| XCTAssertTrue(queryItem.isEqual(queryItemCopy)) |
| } |
| |
| func test_itemNSCoding() { |
| let queryItemA = NSURLQueryItem(name: "id", value: "23") |
| let queryItemB = NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: queryItemA)) as! NSURLQueryItem |
| XCTAssertEqual(queryItemA, queryItemB, "Archived then unarchived query item must be equal.") |
| } |
| |
| func test_dataRepresentation() { |
| let url = NSURL(fileURLWithPath: "/tmp/foo") |
| let url2 = NSURL(dataRepresentation: url.dataRepresentation, |
| relativeTo: nil) |
| XCTAssertEqual(url, url2) |
| } |
| |
| func test_description() { |
| let url = URL(string: "http://amazon.in")! |
| XCTAssertEqual(url.description, "http://amazon.in") |
| var urlComponents = URLComponents() |
| urlComponents.port = 8080 |
| urlComponents.host = "amazon.in" |
| urlComponents.password = "abcd" |
| let relativeURL = urlComponents.url(relativeTo: url) |
| XCTAssertEqual(relativeURL?.description, "//:abcd@amazon.in:8080 -- http://amazon.in") |
| } |
| |
| // MARK: Resource values. |
| |
| func test_URLResourceValues() throws { |
| do { |
| try FileManager.default.createDirectory(at: writableTestDirectoryURL, withIntermediateDirectories: true) |
| var a = writableTestDirectoryURL.appendingPathComponent("a") |
| try Data().write(to: a) |
| |
| // Not all OSes support fractions of a second; remove the fractional part. |
| let (roughlyAYearFromNowInterval, _) = modf(Date(timeIntervalSinceNow: 1 * 365 * 24 * 60 * 60).timeIntervalSinceReferenceDate) |
| let roughlyAYearFromNow = Date(timeIntervalSinceReferenceDate: roughlyAYearFromNowInterval) |
| |
| var values = URLResourceValues() |
| values.contentModificationDate = roughlyAYearFromNow |
| |
| try a.setResourceValues(values) |
| |
| let keys: Set<URLResourceKey> = [ |
| .contentModificationDateKey, |
| ] |
| |
| func assertRelevantValuesAreEqual(in newValues: URLResourceValues) { |
| XCTAssertEqual(values.contentModificationDate, newValues.contentModificationDate) |
| } |
| |
| do { |
| let newValues = try a.resourceValues(forKeys: keys) |
| assertRelevantValuesAreEqual(in: newValues) |
| } |
| |
| do { |
| a.removeAllCachedResourceValues() |
| let newValues = try a.resourceValues(forKeys: keys) |
| assertRelevantValuesAreEqual(in: newValues) |
| } |
| |
| do { |
| let separateA = writableTestDirectoryURL.appendingPathComponent("a") |
| let newValues = try separateA.resourceValues(forKeys: keys) |
| assertRelevantValuesAreEqual(in: newValues) |
| } |
| } catch { |
| if let error = error as? NSError { |
| print("error: \(error.description) - \(error.userInfo)") |
| } else { |
| print("error: \(error)") |
| } |
| throw error |
| } |
| } |
| |
| // MARK: - |
| |
| var writableTestDirectoryURL: URL! |
| |
| override func setUp() { |
| super.setUp() |
| |
| let pid = ProcessInfo.processInfo.processIdentifier |
| writableTestDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("org.swift.TestFoundation.TestURL.resourceValues.\(pid)") |
| } |
| |
| override func tearDown() { |
| if let directoryURL = writableTestDirectoryURL, |
| (try? FileManager.default.attributesOfItem(atPath: directoryURL.path)) != nil { |
| do { |
| try FileManager.default.removeItem(at: directoryURL) |
| } catch { |
| NSLog("Could not remove test directory at URL \(directoryURL): \(error)") |
| } |
| } |
| |
| super.tearDown() |
| } |
| |
| static var allTests: [(String, (TestURL) -> () throws -> Void)] { |
| var tests: [(String, (TestURL) -> () throws -> Void)] = [ |
| ("test_URLStrings", test_URLStrings), |
| ("test_fileURLWithPath_relativeTo", test_fileURLWithPath_relativeTo ), |
| // TODO: these tests fail on linux, more investigation is needed |
| ("test_fileURLWithPath", test_fileURLWithPath), |
| ("test_fileURLWithPath_isDirectory", test_fileURLWithPath_isDirectory), |
| ("test_URLByResolvingSymlinksInPath", test_URLByResolvingSymlinksInPath), |
| ("test_reachable", test_reachable), |
| ("test_copy", test_copy), |
| ("test_itemNSCoding", test_itemNSCoding), |
| ("test_dataRepresentation", test_dataRepresentation), |
| ("test_description", test_description), |
| ("test_URLResourceValues", testExpectedToFail(test_URLResourceValues, |
| "test_URLResourceValues: Except for .nameKey, we have no testable attributes that work in the environment Swift CI uses, for now. SR-XXXX")), |
| ] |
| |
| #if os(Windows) |
| tests.append(contentsOf: [ |
| ("test_WindowsPathSeparator", test_WindowsPathSeparator), |
| ("test_WindowsPathSeparator2", test_WindowsPathSeparator2), |
| ]) |
| #endif |
| |
| return tests |
| } |
| } |
| |
| class TestURLComponents : XCTestCase { |
| static var allTests: [(String, (TestURLComponents) -> () throws -> Void)] { |
| return [ |
| ("test_queryItems", test_queryItems), |
| ("test_string", test_string), |
| ("test_port", test_portSetter), |
| ("test_url", test_url), |
| ("test_copy", test_copy), |
| ("test_hash", test_hash), |
| ("test_createURLWithComponents", test_createURLWithComponents), |
| ("test_path", test_path), |
| ("test_percentEncodedPath", test_percentEncodedPath), |
| ] |
| } |
| |
| func test_queryItems() { |
| let urlString = "http://localhost:8080/foo?bar=&bar=baz" |
| let url = URL(string: urlString)! |
| |
| let components = URLComponents(url: url, resolvingAgainstBaseURL: false) |
| |
| var query = [String: String]() |
| components?.queryItems?.forEach { |
| query[$0.name] = $0.value ?? "" |
| } |
| XCTAssertEqual(["bar": "baz"], query) |
| } |
| |
| func test_string() { |
| for obj in getTestData()! { |
| let testDict = obj as! [String: Any] |
| let unencodedString = testDict[kURLTestUrlKey] as! String |
| let expectedString = NSString(string: unencodedString).addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)! |
| guard let components = URLComponents(string: expectedString) else { continue } |
| XCTAssertEqual(components.string!, expectedString, "should be the expected string (\(components.string!) != \(expectedString))") |
| } |
| } |
| |
| func test_portSetter() { |
| let urlString = "http://myhost.mydomain.com" |
| let port: Int = 8080 |
| let expectedString = "http://myhost.mydomain.com:8080" |
| var url = URLComponents(string: urlString) |
| url!.port = port |
| let receivedString = url!.string |
| XCTAssertEqual(receivedString, expectedString, "expected \(expectedString) but received \(receivedString as Optional)") |
| } |
| |
| func test_url() throws { |
| |
| let baseURL = try XCTUnwrap(URL(string: "https://www.example.com")) |
| |
| /* test NSURLComponents without authority */ |
| guard var compWithAuthority = URLComponents(string: "https://www.swift.org") else { |
| XCTFail("Failed to create URLComponents using 'https://www.swift.org'") |
| return |
| } |
| compWithAuthority.path = "/path/to/file with space.html" |
| compWithAuthority.query = "id=23&search=Foo Bar" |
| var expectedString = "https://www.swift.org/path/to/file%20with%20space.html?id=23&search=Foo%20Bar" |
| XCTAssertEqual(compWithAuthority.string, expectedString, "expected \(expectedString) but received \(compWithAuthority.string as Optional)") |
| |
| guard let urlA = compWithAuthority.url(relativeTo: baseURL) else { |
| XCTFail("URLComponents with authority failed to create relative URL to '\(baseURL)'") |
| return |
| } |
| XCTAssertNil(urlA.baseURL) |
| XCTAssertEqual(urlA.absoluteString, expectedString, "expected \(expectedString) but received \(urlA.absoluteString)") |
| |
| compWithAuthority.path = "path/to/file with space.html" //must start with / |
| XCTAssertNil(compWithAuthority.string) // must be nil |
| XCTAssertNil(compWithAuthority.url(relativeTo: baseURL)) //must be nil |
| |
| /* test NSURLComponents without authority */ |
| var compWithoutAuthority = URLComponents() |
| compWithoutAuthority.path = "path/to/file with space.html" |
| compWithoutAuthority.query = "id=23&search=Foo Bar" |
| expectedString = "path/to/file%20with%20space.html?id=23&search=Foo%20Bar" |
| XCTAssertEqual(compWithoutAuthority.string, expectedString, "expected \(expectedString) but received \(compWithoutAuthority.string as Optional)") |
| |
| guard let urlB = compWithoutAuthority.url(relativeTo: baseURL) else { |
| XCTFail("URLComponents without authority failed to create relative URL to '\(baseURL)'") |
| return |
| } |
| expectedString = "https://www.example.com/path/to/file%20with%20space.html?id=23&search=Foo%20Bar" |
| XCTAssertEqual(urlB.absoluteString, expectedString, "expected \(expectedString) but received \(urlB.absoluteString)") |
| |
| compWithoutAuthority.path = "//path/to/file with space.html" //shouldn't start with // |
| XCTAssertNil(compWithoutAuthority.string) // must be nil |
| XCTAssertNil(compWithoutAuthority.url(relativeTo: baseURL)) //must be nil |
| } |
| |
| func test_copy() { |
| let urlString = "https://www.swift.org/path/to/file.html?id=name" |
| let urlComponent = NSURLComponents(string: urlString)! |
| let copy = urlComponent.copy() as! NSURLComponents |
| |
| /* Assert that NSURLComponents.copy did not return self */ |
| XCTAssertFalse(copy === urlComponent) |
| |
| /* Assert that NSURLComponents.copy is actually a copy of NSURLComponents */ |
| XCTAssertTrue(copy.isEqual(urlComponent)) |
| } |
| |
| func test_hash() { |
| let c1 = URLComponents(string: "https://www.swift.org/path/to/file.html?id=name")! |
| let c2 = URLComponents(string: "https://www.swift.org/path/to/file.html?id=name")! |
| |
| XCTAssertEqual(c1, c2) |
| XCTAssertEqual(c1.hashValue, c2.hashValue) |
| |
| let strings: [String?] = (0..<20).map { "s\($0)" as String? } |
| checkHashing_ValueType( |
| initialValue: URLComponents(), |
| byMutating: \URLComponents.scheme, |
| throughValues: strings) |
| checkHashing_ValueType( |
| initialValue: URLComponents(), |
| byMutating: \URLComponents.user, |
| throughValues: strings) |
| checkHashing_ValueType( |
| initialValue: URLComponents(), |
| byMutating: \URLComponents.password, |
| throughValues: strings) |
| checkHashing_ValueType( |
| initialValue: URLComponents(), |
| byMutating: \URLComponents.host, |
| throughValues: strings) |
| checkHashing_ValueType( |
| initialValue: URLComponents(), |
| byMutating: \URLComponents.port, |
| throughValues: (0..<20).map { $0 as Int? }) |
| checkHashing_ValueType( |
| initialValue: URLComponents(), |
| byMutating: \URLComponents.path, |
| throughValues: strings.compactMap { $0 }) |
| checkHashing_ValueType( |
| initialValue: URLComponents(), |
| byMutating: \URLComponents.query, |
| throughValues: strings) |
| checkHashing_ValueType( |
| initialValue: URLComponents(), |
| byMutating: \URLComponents.fragment, |
| throughValues: strings) |
| |
| checkHashing_NSCopying( |
| initialValue: NSURLComponents(), |
| byMutating: \NSURLComponents.scheme, |
| throughValues: strings) |
| checkHashing_NSCopying( |
| initialValue: NSURLComponents(), |
| byMutating: \NSURLComponents.user, |
| throughValues: strings) |
| checkHashing_NSCopying( |
| initialValue: NSURLComponents(), |
| byMutating: \NSURLComponents.password, |
| throughValues: strings) |
| checkHashing_NSCopying( |
| initialValue: NSURLComponents(), |
| byMutating: \NSURLComponents.host, |
| throughValues: strings) |
| checkHashing_NSCopying( |
| initialValue: NSURLComponents(), |
| byMutating: \NSURLComponents.port, |
| throughValues: (0..<20).map { $0 as NSNumber? }) |
| checkHashing_NSCopying( |
| initialValue: NSURLComponents(), |
| byMutating: \NSURLComponents.path, |
| throughValues: strings) |
| checkHashing_NSCopying( |
| initialValue: NSURLComponents(), |
| byMutating: \NSURLComponents.query, |
| throughValues: strings) |
| checkHashing_NSCopying( |
| initialValue: NSURLComponents(), |
| byMutating: \NSURLComponents.fragment, |
| throughValues: strings) |
| } |
| |
| func test_createURLWithComponents() { |
| let urlComponents = NSURLComponents() |
| urlComponents.scheme = "https"; |
| urlComponents.host = "com.test.swift"; |
| urlComponents.path = "/test/path"; |
| let date = Date() |
| let query1 = URLQueryItem(name: "date", value: date.description) |
| let query2 = URLQueryItem(name: "simpleDict", value: "false") |
| let query3 = URLQueryItem(name: "checkTest", value: "false") |
| let query4 = URLQueryItem(name: "someKey", value: "afsdjhfgsdkf^fhdjgf") |
| urlComponents.queryItems = [query1, query2, query3, query4] |
| XCTAssertNotNil(urlComponents.url?.query) |
| XCTAssertEqual(urlComponents.queryItems?.count, 4) |
| } |
| |
| func test_path() { |
| let c1 = URLComponents() |
| XCTAssertEqual(c1.path, "") |
| |
| let c2 = URLComponents(string: "http://swift.org") |
| XCTAssertEqual(c2?.path, "") |
| |
| let c3 = URLComponents(string: "http://swift.org/") |
| XCTAssertEqual(c3?.path, "/") |
| |
| let c4 = URLComponents(string: "http://swift.org/foo/bar") |
| XCTAssertEqual(c4?.path, "/foo/bar") |
| |
| let c5 = URLComponents(string: "http://swift.org:80/foo/bar") |
| XCTAssertEqual(c5?.path, "/foo/bar") |
| |
| let c6 = URLComponents(string: "http://swift.org:80/foo/b%20r") |
| XCTAssertEqual(c6?.path, "/foo/b r") |
| } |
| |
| func test_percentEncodedPath() { |
| let c1 = URLComponents() |
| XCTAssertEqual(c1.percentEncodedPath, "") |
| |
| let c2 = URLComponents(string: "http://swift.org") |
| XCTAssertEqual(c2?.percentEncodedPath, "") |
| |
| let c3 = URLComponents(string: "http://swift.org/") |
| XCTAssertEqual(c3?.percentEncodedPath, "/") |
| |
| let c4 = URLComponents(string: "http://swift.org/foo/bar") |
| XCTAssertEqual(c4?.percentEncodedPath, "/foo/bar") |
| |
| let c5 = URLComponents(string: "http://swift.org:80/foo/bar") |
| XCTAssertEqual(c5?.percentEncodedPath, "/foo/bar") |
| |
| let c6 = URLComponents(string: "http://swift.org:80/foo/b%20r") |
| XCTAssertEqual(c6?.percentEncodedPath, "/foo/b%20r") |
| } |
| } |