@@ -48,19 +48,57 @@ private func getTestData() -> [Any]? {
4848
4949class TestURL : XCTestCase {
5050 static var allTests : [ ( String , ( TestURL ) -> ( ) throws -> Void ) ] {
51- return [
51+ var tests : [ ( String , ( TestURL ) -> ( ) throws -> Void ) ] = [
5252 ( " test_URLStrings " , test_URLStrings) ,
5353 ( " test_fileURLWithPath_relativeTo " , test_fileURLWithPath_relativeTo ) ,
5454 // TODO: these tests fail on linux, more investigation is needed
5555 ( " test_fileURLWithPath " , test_fileURLWithPath) ,
5656 ( " test_fileURLWithPath_isDirectory " , test_fileURLWithPath_isDirectory) ,
57- ( " test_URLByResolvingSymlinksInPath " , test_URLByResolvingSymlinksInPath) ,
57+ ( " test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators " , test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators) ,
58+ ( " test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators " , test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators) ,
59+ ( " test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators " , test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators) ,
60+ ( " test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory " , test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory) ,
61+ ( " test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory " , test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory) ,
62+ ( " test_resolvingSymlinksInPathShouldResolvesSymlinks " , test_resolvingSymlinksInPathShouldResolvesSymlinks) ,
63+ ( " test_resolvingSymlinksInPathShouldNotChangeNonFileURLs " , test_resolvingSymlinksInPathShouldNotChangeNonFileURLs) ,
64+ ( " test_resolvingSymlinksInPathShouldNotChangePathlessURLs " , test_resolvingSymlinksInPathShouldNotChangePathlessURLs) ,
5865 ( " test_reachable " , test_reachable) ,
5966 ( " test_copy " , test_copy) ,
6067 ( " test_itemNSCoding " , test_itemNSCoding) ,
6168 ( " test_dataRepresentation " , test_dataRepresentation) ,
6269 ( " test_description " , test_description) ,
6370 ]
71+
72+ #if canImport(Darwin)
73+ tests += [
74+ ( " test_resolvingSymlinksInPathShouldRemovePrivatePrefix " , test_resolvingSymlinksInPathShouldRemovePrivatePrefix) ,
75+ ( " test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent " , test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent) ,
76+ ]
77+ #endif
78+
79+ return tests
80+ }
81+
82+ var writableTestDirectoryURL : URL !
83+
84+ override func setUp( ) {
85+ super. setUp ( )
86+
87+ let pid = ProcessInfo . processInfo. processIdentifier
88+ writableTestDirectoryURL = URL ( fileURLWithPath: NSTemporaryDirectory ( ) ) . appendingPathComponent ( " org.swift.TestFoundation.TestURL. \( pid) " )
89+ }
90+
91+ override func tearDown( ) {
92+ if let directoryURL = writableTestDirectoryURL,
93+ ( try ? FileManager . default. attributesOfItem ( atPath: directoryURL. path) ) != nil {
94+ do {
95+ try FileManager . default. removeItem ( at: directoryURL)
96+ } catch {
97+ NSLog ( " Could not remove test directory at URL \( directoryURL) : \( error) " )
98+ }
99+ }
100+
101+ super. tearDown ( )
64102 }
65103
66104 func test_fileURLWithPath_relativeTo( ) {
@@ -383,58 +421,96 @@ class TestURL : XCTestCase {
383421 XCTAssertTrue ( strncmp ( TestURL . gFileDoesNotExistName, relativePath, lengthOfRelativePath) == 0 , " fileSystemRepresentation of file path is wrong " )
384422 }
385423
386- func test_URLByResolvingSymlinksInPath( ) {
387- let files = [
388- NSTemporaryDirectory ( ) + " ABC/test_URLByResolvingSymlinksInPath "
389- ]
390-
391- guard ensureFiles ( files) else {
392- XCTAssert ( false , " Could create files for testing. " )
393- return
394- }
395-
396- // tmp is special because it is symlinked to /private/tmp and this /private prefix should be dropped,
397- // so tmp is tmp. On Linux tmp is not symlinked so it would be the same.
398- do {
399- let url = URL ( fileURLWithPath: " /.//tmp/ABC/.. " )
400- let result = url. resolvingSymlinksInPath ( ) . absoluteString
401- XCTAssertEqual ( result, " file:///tmp/ " , " URLByResolvingSymlinksInPath removes extraneous path components and resolve symlinks. " )
402- }
403-
404- do {
405- let url = URL ( fileURLWithPath: " ~ " )
406- let result = url. resolvingSymlinksInPath ( ) . absoluteString
407- let expected = " file:// " + FileManager. default. currentDirectoryPath + " /~ "
408- XCTAssertEqual ( result, expected, " URLByResolvingSymlinksInPath resolves relative paths using current working directory. " )
409- }
424+ func test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators( ) {
425+ let url = URL ( fileURLWithPath: " //foo///bar////baz/ " )
426+ let result = url. resolvingSymlinksInPath ( )
427+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /foo/bar/baz " ) )
428+ }
410429
411- do {
412- let url = URL ( fileURLWithPath: " anysite.com/search " )
413- let result = url. resolvingSymlinksInPath ( ) . absoluteString
414- let expected = " file:// " + FileManager. default. currentDirectoryPath + " /anysite.com/search "
415- XCTAssertEqual ( result, expected)
416- }
430+ func test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators( ) {
431+ let url = URL ( fileURLWithPath: " /./foo/./.bar/./baz/./ " )
432+ let result = url. resolvingSymlinksInPath ( )
433+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /foo/.bar/baz " ) )
434+ }
417435
418- // tmp is symlinked on macOS only
419- #if os(macOS)
420- do {
421- let url = URL ( fileURLWithPath: " /tmp/.. " )
422- let result = url. resolvingSymlinksInPath ( ) . absoluteString
423- XCTAssertEqual ( result, " file:///private/ " )
424- }
425- #else
426- do {
427- let url = URL ( fileURLWithPath: " /tmp/ABC/test_URLByResolvingSymlinksInPath " )
428- let result = url. resolvingSymlinksInPath ( ) . absoluteString
429- XCTAssertEqual ( result, " file:///tmp/ABC/test_URLByResolvingSymlinksInPath " , " URLByResolvingSymlinksInPath appends trailing slash for existing directories only " )
430- }
431- #endif
436+ func test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators( ) {
437+ let url = URL ( fileURLWithPath: " /foo/../..bar/../baz/ " )
438+ let result = url. resolvingSymlinksInPath ( )
439+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /baz " ) )
440+ }
432441
433- do {
434- let url = URL ( fileURLWithPath: " /tmp/ABC/.. " )
435- let result = url. resolvingSymlinksInPath ( ) . absoluteString
436- XCTAssertEqual ( result, " file:///tmp/ " )
442+ func test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory( ) throws {
443+ let fileManager = FileManager . default
444+ try fileManager. createDirectory ( at: writableTestDirectoryURL, withIntermediateDirectories: true )
445+ defer { try ? fileManager. removeItem ( at: writableTestDirectoryURL) }
446+
447+ let previousCurrentDirectory = fileManager. currentDirectoryPath
448+ fileManager. changeCurrentDirectoryPath ( writableTestDirectoryURL. path)
449+ defer { fileManager. changeCurrentDirectoryPath ( previousCurrentDirectory) }
450+
451+ let url = URL ( fileURLWithPath: " foo/bar/baz " )
452+ let result = url. resolvingSymlinksInPath ( )
453+ XCTAssertEqual ( result, URL ( fileURLWithPath: writableTestDirectoryURL. path + " /foo/bar/baz " ) )
454+ }
455+
456+ func test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory( ) throws {
457+ let fileManager = FileManager . default
458+ try fileManager. createDirectory ( at: writableTestDirectoryURL, withIntermediateDirectories: true )
459+ defer { try ? fileManager. removeItem ( at: writableTestDirectoryURL) }
460+
461+ var path = writableTestDirectoryURL. path
462+ if path. hasSuffix ( " / " ) {
463+ path. remove ( at: path. index ( path. endIndex, offsetBy: - 1 ) )
437464 }
465+ let url = URL ( fileURLWithPath: path)
466+ let result = url. resolvingSymlinksInPath ( )
467+ XCTAssertEqual ( result, URL ( fileURLWithPath: path + " / " ) )
468+ }
469+
470+ func test_resolvingSymlinksInPathShouldResolvesSymlinks( ) throws {
471+ // NOTE: this test only works on file systems that support symlinks.
472+ let fileManager = FileManager . default
473+ try fileManager. createDirectory ( at: writableTestDirectoryURL, withIntermediateDirectories: true )
474+ defer { try ? fileManager. removeItem ( at: writableTestDirectoryURL) }
475+
476+ let symbolicLink = writableTestDirectoryURL. appendingPathComponent ( " origin " )
477+ print ( symbolicLink)
478+ let destination = writableTestDirectoryURL. appendingPathComponent ( " destination " )
479+ print ( destination)
480+ try " " . write ( to: destination, atomically: true , encoding: . utf8)
481+ try fileManager. createSymbolicLink ( at: symbolicLink, withDestinationURL: destination)
482+
483+ let result = symbolicLink. resolvingSymlinksInPath ( )
484+ print ( result)
485+ XCTAssertEqual ( result, URL ( fileURLWithPath: writableTestDirectoryURL. path + " /destination " ) )
486+ }
487+
488+ func test_resolvingSymlinksInPathShouldRemovePrivatePrefix( ) {
489+ // NOTE: this test only works on Darwin, since the code that removes
490+ // /private relies on /private/tmp existing.
491+ let url = URL ( fileURLWithPath: " /private/tmp " )
492+ let result = url. resolvingSymlinksInPath ( )
493+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /tmp " ) )
494+ }
495+
496+ func test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent( ) {
497+ // NOTE: this test only works on Darwin, since only there /tmp is
498+ // symlinked to /private/tmp.
499+ let url = URL ( fileURLWithPath: " /tmp/.. " )
500+ let result = url. resolvingSymlinksInPath ( )
501+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /private " ) )
502+ }
503+
504+ func test_resolvingSymlinksInPathShouldNotChangeNonFileURLs( ) {
505+ let url = URL ( string: " myscheme://server/foo/bar/baz " ) !
506+ let result = url. resolvingSymlinksInPath ( ) . absoluteString
507+ XCTAssertEqual ( result, " myscheme://server/foo/bar/baz " )
508+ }
509+
510+ func test_resolvingSymlinksInPathShouldNotChangePathlessURLs( ) {
511+ let url = URL ( string: " file:// " ) !
512+ let result = url. resolvingSymlinksInPath ( ) . absoluteString
513+ XCTAssertEqual ( result, " file:// " )
438514 }
439515
440516 func test_reachable( ) {
0 commit comments