@@ -934,6 +934,72 @@ class TestFileManager : XCTestCase {
934
934
}
935
935
XCTAssertNil ( try ? fm. linkItem ( atPath: srcLink, toPath: destLink) , " Creating link where one already exists " )
936
936
}
937
+
938
+ func test_resolvingSymlinksInPath( ) throws {
939
+ try withTemporaryDirectory { ( temporaryDirectoryURL, _) in
940
+ // Initialization
941
+ var baseURL = temporaryDirectoryURL
942
+ . appendingPathComponent ( " test_resolvingSymlinksInPath " )
943
+ . appendingPathComponent ( UUID ( ) . uuidString)
944
+
945
+ try FileManager . default. createDirectory ( at: baseURL, withIntermediateDirectories: true )
946
+ let testData = Data ( [ 0x01 ] )
947
+
948
+ baseURL. resolveSymlinksInPath ( )
949
+ baseURL. standardize ( )
950
+
951
+ let link1URL = baseURL. appendingPathComponent ( " link1 " )
952
+ let link2URL = baseURL. appendingPathComponent ( " link2 " )
953
+ let link3URL = baseURL. appendingPathComponent ( " link3 " )
954
+ let testFileURL = baseURL. appendingPathComponent ( " test " ) . standardized. absoluteURL
955
+
956
+ try FileManager . default. removeItem ( at: baseURL)
957
+
958
+ // A) Check non-symbolic linking resolution
959
+ try FileManager . default. createDirectory ( at: baseURL, withIntermediateDirectories: true )
960
+ try testData. write ( to: testFileURL)
961
+ let resolvedURL_A = testFileURL. resolvingSymlinksInPath ( ) . standardized. absoluteURL
962
+ XCTAssertEqual ( resolvedURL_A. path, testFileURL. path)
963
+ try FileManager . default. removeItem ( at: baseURL)
964
+
965
+ // B) Check simple symbolic linking resolution
966
+ try FileManager . default. createDirectory ( at: baseURL, withIntermediateDirectories: true )
967
+ try testData. write ( to: testFileURL)
968
+ try FileManager . default. createSymbolicLink ( at: link1URL, withDestinationURL: testFileURL)
969
+ let resolvedURL_B = link1URL. resolvingSymlinksInPath ( ) . standardized. absoluteURL
970
+ XCTAssertEqual ( resolvedURL_B. path, testFileURL. path)
971
+ try FileManager . default. removeItem ( at: baseURL)
972
+
973
+ // C) Check recursive symbolic linking resolution
974
+ //
975
+ // Note: The symbolic link creation order is important as in some platforms like Windows
976
+ // symlinks can only be created pointing to existing targets.
977
+ try FileManager . default. createDirectory ( at: baseURL, withIntermediateDirectories: true )
978
+ try testData. write ( to: testFileURL)
979
+ try FileManager . default. createSymbolicLink ( at: link2URL, withDestinationURL: testFileURL)
980
+ try FileManager . default. createSymbolicLink ( at: link1URL, withDestinationURL: link2URL)
981
+ let resolvedURL_C = link1URL. resolvingSymlinksInPath ( ) . standardized. absoluteURL
982
+ XCTAssertEqual ( resolvedURL_C. path, testFileURL. path)
983
+
984
+ // C-2) And that FileManager.destinationOfSymbolicLink(atPath:) does not recursively resolves them
985
+ let destinationOfSymbolicLink1 = try FileManager . default. destinationOfSymbolicLink ( atPath: link1URL. path)
986
+ let destinationOfSymbolicLink1URL = URL ( fileURLWithPath: destinationOfSymbolicLink1) . standardized. absoluteURL
987
+ XCTAssertEqual ( destinationOfSymbolicLink1URL. path, link2URL. path)
988
+ try FileManager . default. removeItem ( at: baseURL)
989
+
990
+ #if !os(Windows)
991
+ // D) Check infinite recursion loops are stopped and the function returns the intial symlink
992
+ //
993
+ // Note: This cannot be tested on platforms which only support creating symlinks pointing to existing targets.
994
+ try FileManager . default. createDirectory ( at: baseURL, withIntermediateDirectories: true )
995
+ try FileManager . default. createSymbolicLink ( at: link1URL, withDestinationURL: link2URL)
996
+ try FileManager . default. createSymbolicLink ( at: link2URL, withDestinationURL: link3URL)
997
+ try FileManager . default. createSymbolicLink ( at: link3URL, withDestinationURL: link1URL)
998
+ let resolvedURL_D = link1URL. resolvingSymlinksInPath ( )
999
+ XCTAssertEqual ( resolvedURL_D. lastPathComponent, link1URL. lastPathComponent)
1000
+ #endif
1001
+ }
1002
+ }
937
1003
938
1004
func test_homedirectoryForUser( ) {
939
1005
let filemanger = FileManager . default
@@ -1849,6 +1915,7 @@ VIDEOS=StopgapVideos
1849
1915
( " test_subpathsOfDirectoryAtPath " , test_subpathsOfDirectoryAtPath) ,
1850
1916
( " test_copyItemAtPathToPath " , test_copyItemAtPathToPath) ,
1851
1917
( " test_linkItemAtPathToPath " , testExpectedToFailOnAndroid ( test_linkItemAtPathToPath, " Android doesn't allow hard links " ) ) ,
1918
+ ( " test_resolvingSymlinksInPath " , test_resolvingSymlinksInPath) ,
1852
1919
( " test_homedirectoryForUser " , test_homedirectoryForUser) ,
1853
1920
( " test_temporaryDirectoryForUser " , test_temporaryDirectoryForUser) ,
1854
1921
( " test_creatingDirectoryWithShortIntermediatePath " , test_creatingDirectoryWithShortIntermediatePath) ,
0 commit comments