@@ -380,60 +380,103 @@ class TestURL : XCTestCase {
380
380
XCTAssertTrue ( strncmp ( TestURL . gFileDoesNotExistName, relativePath, lengthOfRelativePath) == 0 , " fileSystemRepresentation of file path is wrong " )
381
381
}
382
382
383
- func test_URLByResolvingSymlinksInPath( ) {
384
- let files = [
385
- NSTemporaryDirectory ( ) + " ABC/test_URLByResolvingSymlinksInPath "
386
- ]
387
-
388
- guard ensureFiles ( files) else {
389
- XCTAssert ( false , " Could create files for testing. " )
390
- return
391
- }
392
-
393
- // tmp is special because it is symlinked to /private/tmp and this /private prefix should be dropped,
394
- // so tmp is tmp. On Linux tmp is not symlinked so it would be the same.
395
- do {
396
- let url = URL ( fileURLWithPath: " /.//tmp/ABC/.. " )
397
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
398
- XCTAssertEqual ( result, " file:///tmp/ " , " URLByResolvingSymlinksInPath removes extraneous path components and resolve symlinks. " )
399
- }
383
+ func test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators( ) {
384
+ let url = URL ( fileURLWithPath: " //foo///bar////baz/ " )
385
+ let result = url. resolvingSymlinksInPath ( )
386
+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /foo/bar/baz " ) )
387
+ }
400
388
401
- do {
402
- let url = URL ( fileURLWithPath: " ~ " )
403
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
404
- let expected = " file:// " + FileManager. default. currentDirectoryPath + " /~ "
405
- XCTAssertEqual ( result, expected, " URLByResolvingSymlinksInPath resolves relative paths using current working directory. " )
406
- }
389
+ func test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators( ) {
390
+ let url = URL ( fileURLWithPath: " /./foo/./.bar/./baz/./ " )
391
+ let result = url. resolvingSymlinksInPath ( )
392
+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /foo/.bar/baz " ) )
393
+ }
407
394
408
- do {
409
- let url = URL ( fileURLWithPath: " anysite.com/search " )
410
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
411
- let expected = " file:// " + FileManager. default. currentDirectoryPath + " /anysite.com/search "
412
- XCTAssertEqual ( result, expected)
413
- }
395
+ func test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators( ) {
396
+ let url = URL ( fileURLWithPath: " /foo/../..bar/../baz/ " )
397
+ let result = url. resolvingSymlinksInPath ( )
398
+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /baz " ) )
399
+ }
414
400
415
- // tmp is symlinked on macOS only
416
- #if os(macOS)
417
- do {
418
- let url = URL ( fileURLWithPath: " /tmp/.. " )
419
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
420
- XCTAssertEqual ( result, " file:///private/ " )
421
- }
422
- #else
423
- do {
424
- let url = URL ( fileURLWithPath: " /tmp/ABC/test_URLByResolvingSymlinksInPath " )
425
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
426
- XCTAssertEqual ( result, " file:///tmp/ABC/test_URLByResolvingSymlinksInPath " , " URLByResolvingSymlinksInPath appends trailing slash for existing directories only " )
427
- }
428
- #endif
401
+ func test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory( ) throws {
402
+ let fileManager = FileManager . default
403
+ try fileManager. createDirectory ( at: writableTestDirectoryURL, withIntermediateDirectories: true )
404
+ defer { try ? fileManager. removeItem ( at: writableTestDirectoryURL) }
429
405
430
- do {
431
- let url = URL ( fileURLWithPath: " /tmp/ABC/.. " )
432
- let result = url. resolvingSymlinksInPath ( ) . absoluteString
433
- XCTAssertEqual ( result, " file:///tmp/ " )
406
+ let previousCurrentDirectory = fileManager. currentDirectoryPath
407
+ fileManager. changeCurrentDirectoryPath ( writableTestDirectoryURL. path)
408
+ defer { fileManager. changeCurrentDirectoryPath ( previousCurrentDirectory) }
409
+
410
+ // In Darwin, because temporary directory is inside /private,
411
+ // writableTestDirectoryURL will be something like /var/folders/...,
412
+ // but /var points to /private/var, which is only removed if the
413
+ // destination exists, so we create the destination to avoid having to
414
+ // compare against /private in Darwin.
415
+ try fileManager. createDirectory ( at: writableTestDirectoryURL. appendingPathComponent ( " foo/bar " ) , withIntermediateDirectories: true )
416
+ try " " . write ( to: writableTestDirectoryURL. appendingPathComponent ( " foo/bar/baz " ) , atomically: true , encoding: . utf8)
417
+
418
+ let url = URL ( fileURLWithPath: " foo/bar/baz " )
419
+ let result = url. resolvingSymlinksInPath ( )
420
+ XCTAssertEqual ( result, URL ( fileURLWithPath: writableTestDirectoryURL. path + " /foo/bar/baz " ) )
421
+ }
422
+
423
+ func test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory( ) throws {
424
+ let fileManager = FileManager . default
425
+ try fileManager. createDirectory ( at: writableTestDirectoryURL, withIntermediateDirectories: true )
426
+ defer { try ? fileManager. removeItem ( at: writableTestDirectoryURL) }
427
+
428
+ var path = writableTestDirectoryURL. path
429
+ if path. hasSuffix ( " / " ) {
430
+ path. remove ( at: path. index ( path. endIndex, offsetBy: - 1 ) )
434
431
}
432
+ let url = URL ( fileURLWithPath: path)
433
+ let result = url. resolvingSymlinksInPath ( )
434
+ XCTAssertEqual ( result, URL ( fileURLWithPath: path + " / " ) )
435
435
}
436
-
436
+
437
+ func test_resolvingSymlinksInPathShouldResolveSymlinks( ) throws {
438
+ // NOTE: this test only works on file systems that support symlinks.
439
+ let fileManager = FileManager . default
440
+ try fileManager. createDirectory ( at: writableTestDirectoryURL, withIntermediateDirectories: true )
441
+ defer { try ? fileManager. removeItem ( at: writableTestDirectoryURL) }
442
+
443
+ let symbolicLink = writableTestDirectoryURL. appendingPathComponent ( " origin " )
444
+ let destination = writableTestDirectoryURL. appendingPathComponent ( " destination " )
445
+ try " " . write ( to: destination, atomically: true , encoding: . utf8)
446
+ try fileManager. createSymbolicLink ( at: symbolicLink, withDestinationURL: destination)
447
+
448
+ let result = symbolicLink. resolvingSymlinksInPath ( )
449
+ XCTAssertEqual ( result, URL ( fileURLWithPath: writableTestDirectoryURL. path + " /destination " ) )
450
+ }
451
+
452
+ func test_resolvingSymlinksInPathShouldRemovePrivatePrefix( ) {
453
+ // NOTE: this test only works on Darwin, since the code that removes
454
+ // /private relies on /private/tmp existing.
455
+ let url = URL ( fileURLWithPath: " /private/tmp " )
456
+ let result = url. resolvingSymlinksInPath ( )
457
+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /tmp " ) )
458
+ }
459
+
460
+ func test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent( ) {
461
+ // NOTE: this test only works on Darwin, since only there /tmp is
462
+ // symlinked to /private/tmp.
463
+ let url = URL ( fileURLWithPath: " /tmp/.. " )
464
+ let result = url. resolvingSymlinksInPath ( )
465
+ XCTAssertEqual ( result, URL ( fileURLWithPath: " /private " ) )
466
+ }
467
+
468
+ func test_resolvingSymlinksInPathShouldNotChangeNonFileURLs( ) {
469
+ let url = URL ( string: " myscheme://server/foo/bar/baz " ) !
470
+ let result = url. resolvingSymlinksInPath ( ) . absoluteString
471
+ XCTAssertEqual ( result, " myscheme://server/foo/bar/baz " )
472
+ }
473
+
474
+ func test_resolvingSymlinksInPathShouldNotChangePathlessURLs( ) {
475
+ let url = URL ( string: " file:// " ) !
476
+ let result = url. resolvingSymlinksInPath ( ) . absoluteString
477
+ XCTAssertEqual ( result, " file:// " )
478
+ }
479
+
437
480
func test_reachable( ) {
438
481
#if os(Android)
439
482
var url = URL ( fileURLWithPath: " /data " )
@@ -604,13 +647,20 @@ class TestURL : XCTestCase {
604
647
}
605
648
606
649
static var allTests : [ ( String , ( TestURL ) -> ( ) throws -> Void ) ] {
607
- return [
650
+ var tests : [ ( String , ( TestURL ) -> ( ) throws -> Void ) ] = [
608
651
( " test_URLStrings " , test_URLStrings) ,
609
652
( " test_fileURLWithPath_relativeTo " , test_fileURLWithPath_relativeTo ) ,
610
653
// TODO: these tests fail on linux, more investigation is needed
611
654
( " test_fileURLWithPath " , test_fileURLWithPath) ,
612
655
( " test_fileURLWithPath_isDirectory " , test_fileURLWithPath_isDirectory) ,
613
- ( " test_URLByResolvingSymlinksInPath " , test_URLByResolvingSymlinksInPath) ,
656
+ ( " test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators " , test_URLByResolvingSymlinksInPathShouldRemoveDuplicatedPathSeparators) ,
657
+ ( " test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators " , test_URLByResolvingSymlinksInPathShouldRemoveSingleDotsBetweenSeparators) ,
658
+ ( " test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators " , test_URLByResolvingSymlinksInPathShouldCompressDoubleDotsBetweenSeparators) ,
659
+ ( " test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory " , test_URLByResolvingSymlinksInPathShouldUseTheCurrentDirectory) ,
660
+ ( " test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory " , test_resolvingSymlinksInPathShouldAppendTrailingSlashWhenExistingDirectory) ,
661
+ ( " test_resolvingSymlinksInPathShouldResolveSymlinks " , test_resolvingSymlinksInPathShouldResolveSymlinks) ,
662
+ ( " test_resolvingSymlinksInPathShouldNotChangeNonFileURLs " , test_resolvingSymlinksInPathShouldNotChangeNonFileURLs) ,
663
+ ( " test_resolvingSymlinksInPathShouldNotChangePathlessURLs " , test_resolvingSymlinksInPathShouldNotChangePathlessURLs) ,
614
664
( " test_reachable " , test_reachable) ,
615
665
( " test_copy " , test_copy) ,
616
666
( " test_itemNSCoding " , test_itemNSCoding) ,
@@ -619,6 +669,15 @@ class TestURL : XCTestCase {
619
669
( " test_URLResourceValues " , testExpectedToFail ( test_URLResourceValues,
620
670
" test_URLResourceValues: Except for .nameKey, we have no testable attributes that work in the environment Swift CI uses, for now. SR-XXXX " ) ) ,
621
671
]
672
+
673
+ #if canImport(Darwin)
674
+ tests += [
675
+ ( " test_resolvingSymlinksInPathShouldRemovePrivatePrefix " , test_resolvingSymlinksInPathShouldRemovePrivatePrefix) ,
676
+ ( " test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent " , test_resolvingSymlinksInPathShouldNotRemovePrivatePrefixIfOnlyComponent) ,
677
+ ]
678
+ #endif
679
+
680
+ return tests
622
681
}
623
682
}
624
683
0 commit comments