@@ -473,70 +473,101 @@ class TestURL : XCTestCase {
473
473
XCTAssertTrue ( strncmp ( TestURL . gFileDoesNotExistName, relativePath, lengthOfRelativePath) == 0 , " fileSystemRepresentation of file path is wrong " )
474
474
}
475
475
476
- func test_URLByResolvingSymlinksInPath( ) {
477
- let files = [
478
- NSTemporaryDirectory ( ) + " ABC/test_URLByResolvingSymlinksInPath "
479
- ]
476
+ func test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators( ) {
477
+ let url = URL ( fileURLWithPath: " //foo///bar////baz/ " )
478
+ let result = url. resolvingSymlinksInPath ( )
479
+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /foo/bar/baz " ) )
480
+ }
480
481
481
- guard ensureFiles ( files) else {
482
- XCTAssert ( false , " Could create files for testing. " )
483
- return
484
- }
482
+ func test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators( ) {
483
+ let url = URL ( fileURLWithPath: " /./foo/./.bar/./baz/./ " )
484
+ let result = url. resolvingSymlinksInPath ( )
485
+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /foo/.bar/baz " ) )
486
+ }
485
487
486
- // tmp is special because it is symlinked to /private/tmp and this /private prefix should be dropped,
487
- // so tmp is tmp. On Linux tmp is not symlinked so it would be the same.
488
- do {
489
- let url = URL ( fileURLWithPath: " /.//tmp/ABC/.. " )
490
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
491
- XCTAssertEqual ( result, " file:///tmp/ " , " URLByResolvingSymlinksInPath removes extraneous path components and resolve symlinks. " )
492
- }
488
+ func test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators( ) {
489
+ let url = URL ( fileURLWithPath: " /foo/../..bar/../baz/ " )
490
+ let result = url. resolvingSymlinksInPath ( )
491
+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /baz " ) )
492
+ }
493
493
494
- do {
495
- let url = URL ( fileURLWithPath: " ~ " )
496
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
497
- #if os(Windows)
498
- // On Windows `currentDirectoryPath` will return something like
499
- // `C:/Users/...` which doesn't have a leading slash
500
- let expected = " file:/// " + FileManager. default. currentDirectoryPath + " /~ "
501
- #else
502
- let expected = " file:// " + FileManager. default. currentDirectoryPath + " /~ "
503
- #endif
504
- XCTAssertEqual ( result, expected, " URLByResolvingSymlinksInPath resolves relative paths using current working directory. " )
505
- }
494
+ func test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory( ) throws {
495
+ let fileManager = FileManager . default
496
+ try fileManager. createDirectory ( at: writableTestDirectoryURL, withIntermediateDirectories: true )
497
+ defer { try ? fileManager. removeItem ( at: writableTestDirectoryURL) }
498
+
499
+ let previousCurrentDirectory = fileManager. currentDirectoryPath
500
+ fileManager. changeCurrentDirectoryPath ( writableTestDirectoryURL. path)
501
+ defer { fileManager. changeCurrentDirectoryPath ( previousCurrentDirectory) }
502
+
503
+ // In Darwin, because temporary directory is inside /private,
504
+ // writableTestDirectoryURL will be something like /var/folders/...,
505
+ // but /var points to /private/var, which is only removed if the
506
+ // destination exists, so we create the destination to avoid having to
507
+ // compare against /private in Darwin.
508
+ try fileManager. createDirectory ( at: writableTestDirectoryURL. appendingPathComponent ( " foo/bar " ) , withIntermediateDirectories: true )
509
+ try " " . write ( to: writableTestDirectoryURL. appendingPathComponent ( " foo/bar/baz " ) , atomically: true , encoding: . utf8)
510
+
511
+ let url = URL ( fileURLWithPath: " foo/bar/baz " )
512
+ let result = url. resolvingSymlinksInPath ( )
513
+ XCTAssertEqual ( result, URL ( fileURLWithPath: writableTestDirectoryURL. path + " /foo/bar/baz " ) )
514
+ }
506
515
507
- do {
508
- let url = URL ( fileURLWithPath: " anysite.com/search " )
509
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
510
- #if os(Windows)
511
- // On Windows `currentDirectoryPath` will return something like
512
- // `C:/Users/...` which doesn't have a leading slash
513
- let expected = " file:/// " + FileManager. default. currentDirectoryPath + " /anysite.com/search "
514
- #else
515
- let expected = " file:// " + FileManager. default. currentDirectoryPath + " /anysite.com/search "
516
- #endif
517
- XCTAssertEqual ( result, expected)
518
- }
516
+ func test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory( ) throws {
517
+ let fileManager = FileManager . default
518
+ try fileManager. createDirectory ( at: writableTestDirectoryURL, withIntermediateDirectories: true )
519
+ defer { try ? fileManager. removeItem ( at: writableTestDirectoryURL) }
519
520
520
- // tmp is symlinked on macOS only
521
- #if os(macOS)
522
- do {
523
- let url = URL ( fileURLWithPath: " /tmp/.. " )
524
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
525
- XCTAssertEqual ( result, " file:///private/ " )
521
+ var path = writableTestDirectoryURL. path
522
+ if path. hasSuffix ( " / " ) {
523
+ path. remove ( at: path. index ( path. endIndex, offsetBy: - 1 ) )
526
524
}
527
- #else
528
- do {
529
- let url = URL ( fileURLWithPath: " /tmp/ABC/test_URLByResolvingSymlinksInPath " )
530
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
531
- XCTAssertEqual ( result, " file:///tmp/ABC/test_URLByResolvingSymlinksInPath " , " URLByResolvingSymlinksInPath appends trailing slash for existing directories only " )
532
- }
533
- #endif
525
+ let url = URL ( fileURLWithPath: path)
526
+ let result = url. resolvingSymlinksInPath ( )
527
+ XCTAssertEqual ( result, URL ( fileURLWithPath: path + " / " ) )
528
+ }
534
529
535
- do {
536
- let url = URL ( fileURLWithPath: " /tmp/ABC/.. " )
537
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
538
- XCTAssertEqual ( result, " file:///tmp/ " )
539
- }
530
+ func test_resolvingSymlinksInPathShouldResolveSymlinks( ) throws {
531
+ // NOTE: this test only works on file systems that support symlinks.
532
+ let fileManager = FileManager . default
533
+ try fileManager. createDirectory ( at: writableTestDirectoryURL, withIntermediateDirectories: true )
534
+ defer { try ? fileManager. removeItem ( at: writableTestDirectoryURL) }
535
+
536
+ let symbolicLink = writableTestDirectoryURL. appendingPathComponent ( " origin " )
537
+ let destination = writableTestDirectoryURL. appendingPathComponent ( " destination " )
538
+ try " " . write ( to: destination, atomically: true , encoding: . utf8)
539
+ try fileManager. createSymbolicLink ( at: symbolicLink, withDestinationURL: destination)
540
+
541
+ let result = symbolicLink. resolvingSymlinksInPath ( )
542
+ XCTAssertEqual ( result, URL ( fileURLWithPath: writableTestDirectoryURL. path + " /destination " ) )
543
+ }
544
+
545
+ func test_resolvingSymlinksInPathShouldRemovePrivatePrefix( ) {
546
+ // NOTE: this test only works on Darwin, since the code that removes
547
+ // /private relies on /private/tmp existing.
548
+ let url = URL ( fileURLWithPath: " /private/tmp " )
549
+ let result = url. resolvingSymlinksInPath ( )
550
+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /tmp " ) )
551
+ }
552
+
553
+ func test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent( ) {
554
+ // NOTE: this test only works on Darwin, since only there /tmp is
555
+ // symlinked to /private/tmp.
556
+ let url = URL ( fileURLWithPath: " /tmp/.. " )
557
+ let result = url. resolvingSymlinksInPath ( )
558
+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /private " ) )
559
+ }
560
+
561
+ func test_resolvingSymlinksInPathShouldNotChangeNonFileURLs( ) throws {
562
+ let url = try XCTUnwrap ( URL ( string: " myscheme://server/foo/bar/baz " ) )
563
+ let result = url. resolvingSymlinksInPath ( ) . absoluteString
564
+ XCTAssertEqual ( result, " myscheme://server/foo/bar/baz " )
565
+ }
566
+
567
+ func test_resolvingSymlinksInPathShouldNotChangePathlessURLs( ) throws {
568
+ let url = try XCTUnwrap ( URL ( string: " file:// " ) )
569
+ let result = url. resolvingSymlinksInPath ( ) . absoluteString
570
+ XCTAssertEqual ( result, " file:// " )
540
571
}
541
572
542
573
func test_reachable( ) {
@@ -719,7 +750,14 @@ class TestURL : XCTestCase {
719
750
// TODO: these tests fail on linux, more investigation is needed
720
751
( " test_fileURLWithPath " , test_fileURLWithPath) ,
721
752
( " test_fileURLWithPath_isDirectory " , test_fileURLWithPath_isDirectory) ,
722
- ( " test_URLByResolvingSymlinksInPath " , test_URLByResolvingSymlinksInPath) ,
753
+ ( " test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators " , test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators) ,
754
+ ( " test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators " , test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators) ,
755
+ ( " test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators " , test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators) ,
756
+ ( " test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory " , test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory) ,
757
+ ( " test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory " , test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory) ,
758
+ ( " test_resolvingSymlinksInPathShouldResolveSymlinks " , test_resolvingSymlinksInPathShouldResolveSymlinks) ,
759
+ ( " test_resolvingSymlinksInPathShouldNotChangeNonFileURLs " , test_resolvingSymlinksInPathShouldNotChangeNonFileURLs) ,
760
+ ( " test_resolvingSymlinksInPathShouldNotChangePathlessURLs " , test_resolvingSymlinksInPathShouldNotChangePathlessURLs) ,
723
761
( " test_reachable " , test_reachable) ,
724
762
( " test_copy " , test_copy) ,
725
763
( " test_itemNSCoding " , test_itemNSCoding) ,
@@ -736,6 +774,13 @@ class TestURL : XCTestCase {
736
774
] )
737
775
#endif
738
776
777
+ #if canImport(Darwin)
778
+ tests += [
779
+ ( " test_resolvingSymlinksInPathShouldRemovePrivatePrefix " , test_resolvingSymlinksInPathShouldRemovePrivatePrefix) ,
780
+ ( " test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent " , test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent) ,
781
+ ]
782
+ #endif
783
+
739
784
return tests
740
785
}
741
786
}
0 commit comments