@@ -1293,21 +1293,112 @@ public class SymbolicLink
12931293 /// <remark>Implementation of create symbolic links doesn't work on linux so this test is discard on Mono</remark>
12941294 /// </summary>
12951295 [ Test ]
1296- [ Ignore ( "Test Broken" ) ]
12971296 public void CreateSymbolicLinkOnDirectory ( )
12981297 {
1299- if ( ! Util . IsRunningInMono ( ) )
1298+ var tempBase = Path . Combine ( Path . GetTempPath ( ) , $ "test-symlink-dir-{ Guid . NewGuid ( ) : N} ") ;
1299+ var tempSource = Path . Combine ( tempBase , $ "test-source") ;
1300+ var tempSourceRelative = Path . Combine ( tempBase , $ "..\\ { new DirectoryInfo ( tempBase ) . Name } \\ test-source") ;
1301+ var tempSourceNonEmpty = Path . Combine ( tempBase , $ "test-source-nonempty") ;
1302+ var tempSourceNonEmptyFile = Path . Combine ( tempSourceNonEmpty , $ "test1.txt") ;
1303+ var tempDestination1 = Path . Combine ( tempBase , $ "test-destination1") ;
1304+ var tempDestination1File = Path . Combine ( tempDestination1 , $ "test2.txt") ;
1305+ var tempDestination2 = Path . Combine ( tempBase , $ "test-destination2") ;
1306+
1307+ try
13001308 {
1301- var tempDirectory1 = Directory . CreateDirectory ( Path . GetTempPath ( ) + Path . DirectorySeparatorChar + "test-source" ) ;
1302- var tempDirectory2 = Directory . CreateDirectory ( Path . GetTempPath ( ) + Path . DirectorySeparatorChar + "test-destination" ) ;
1309+ Directory . CreateDirectory ( tempDestination1 ) ;
1310+ File . WriteAllText ( tempDestination1File , "Some content" ) ;
1311+ Directory . CreateDirectory ( tempDestination2 ) ;
1312+
1313+ // Invalid case: source and destination are the same
1314+ Assert . Throws < IOException > ( ( ) => Util . CreateOrUpdateSymbolicLink ( Path . GetTempPath ( ) , Path . GetTempPath ( ) , true ) ) ;
1315+
1316+ // Validate creation of a new symbolic link
1317+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSource , tempDestination1 , true ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . Created ) ) ;
1318+ Assert . True ( new DirectoryInfo ( tempSource ) . Attributes . HasFlag ( FileAttributes . ReparsePoint ) ) ;
1319+ Assert . That ( Directory . ResolveLinkTarget ( tempSource , false ) . FullName , Is . EqualTo ( tempDestination1 ) ) ;
1320+
1321+ // Validate updating a symbolic
1322+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSource , tempDestination2 , true ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . Updated ) ) ;
1323+ Assert . True ( new DirectoryInfo ( tempSource ) . Attributes . HasFlag ( FileAttributes . ReparsePoint ) ) ;
1324+ Assert . That ( Directory . ResolveLinkTarget ( tempSource , false ) . FullName , Is . EqualTo ( tempDestination2 ) ) ;
1325+ Assert . True ( File . Exists ( tempDestination1File ) ) ; // Verify that the content of the old symlink is still there
1326+
1327+ // Validate noop when the symbolic link is already up to date
1328+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSource , tempDestination2 , true ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . AlreadyUpToDate ) ) ;
1329+
1330+ // Validate with alt directory separator char
1331+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSource . Replace ( Path . DirectorySeparatorChar , Path . AltDirectorySeparatorChar ) , tempDestination2 , true ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . AlreadyUpToDate ) ) ;
1332+
1333+ // Validate with relative path
1334+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSourceRelative , tempDestination2 , true ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . AlreadyUpToDate ) ) ;
1335+
1336+ // Validate that creating a symbolic link on a non empty directory succeeds (deleting its content)
1337+ Directory . CreateDirectory ( tempSourceNonEmpty ) ;
1338+ File . WriteAllText ( tempSourceNonEmptyFile , "Some content" ) ;
1339+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSourceNonEmpty , tempDestination1 , true ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . Updated ) ) ;
1340+ Assert . False ( File . Exists ( tempSourceNonEmptyFile ) ) ; // Should have been deleted when the symlink was created
1341+ }
1342+ finally
1343+ {
1344+ try { Directory . Delete ( tempBase , true ) ; } catch { }
1345+ }
1346+ }
13031347
1304- Assert . False ( Util . CreateSymbolicLink ( Path . GetTempPath ( ) , Path . GetTempPath ( ) , true ) ) ;
1305- Assert . False ( tempDirectory1 . Attributes . HasFlag ( FileAttributes . ReparsePoint ) ) ;
1306- Assert . True ( Util . CreateSymbolicLink ( tempDirectory1 . FullName , tempDirectory2 . FullName , true ) ) ;
1307- Assert . True ( tempDirectory1 . Attributes . HasFlag ( FileAttributes . ReparsePoint ) ) ;
1348+ /// <summary>
1349+ /// <c>CreateSymbolicLinkOnFile</c> create a symbolic link for files
1350+ /// The test cases are:
1351+ /// <list type="number">
1352+ /// <item><description>Testing that a symbolic link is not created on a file pointing itself</description></item>
1353+ /// <item><description>Testing that a symbolic link is created on a file pointing to another file</description></item>
1354+ /// <item><description>Testing updating a file symbolic link to point to a different target</description></item>
1355+ /// <item><description>Testing that no operation occurs when file symbolic link is already up to date</description></item>
1356+ /// </list>
1357+ /// <remark>Implementation of create symbolic links doesn't work on linux so this test is discard on Mono</remark>
1358+ /// </summary>
1359+ [ Test ]
1360+ public void CreateSymbolicLinkOnFile ( )
1361+ {
1362+ var tempBase = Path . Combine ( Path . GetTempPath ( ) , $ "test-symlink-file-{ Guid . NewGuid ( ) : N} ") ;
1363+ var tempSource = Path . Combine ( tempBase , $ "test-file-source.txt") ;
1364+ var tempSourceRelative = Path . Combine ( tempBase , $ "..\\ { new DirectoryInfo ( tempBase ) . Name } \\ test-file-source.txt") ;
1365+ var tempDestination1 = Path . Combine ( tempBase , $ "test-file-destination1.txt") ;
1366+ var tempDestination2 = Path . Combine ( tempBase , $ "test-file-destination2.txt") ;
13081367
1309- Directory . Delete ( tempDirectory1 . FullName ) ;
1310- Directory . Delete ( tempDirectory2 . FullName ) ;
1368+ try
1369+ {
1370+ // Create destination files with some content
1371+ Directory . CreateDirectory ( tempBase ) ;
1372+ File . WriteAllText ( tempDestination1 , "Destination 1 content" ) ;
1373+ File . WriteAllText ( tempDestination2 , "Destination 2 content" ) ;
1374+
1375+ // Invalid case: source and destination are the same
1376+ Assert . Throws < IOException > ( ( ) => Util . CreateOrUpdateSymbolicLink ( tempDestination1 , tempDestination1 , false ) ) ;
1377+
1378+ // Validate creation of a new symbolic link
1379+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSource , tempDestination1 , false ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . Created ) ) ;
1380+ Assert . True ( new FileInfo ( tempSource ) . Attributes . HasFlag ( FileAttributes . ReparsePoint ) ) ;
1381+ Assert . That ( File . ResolveLinkTarget ( tempSource , false ) . FullName , Is . EqualTo ( tempDestination1 ) ) ;
1382+ Assert . True ( Util . IsSymbolicLink ( tempSource ) ) ;
1383+
1384+ // Validate updating a symbolic link
1385+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSource , tempDestination2 , false ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . Updated ) ) ;
1386+ Assert . True ( new FileInfo ( tempSource ) . Attributes . HasFlag ( FileAttributes . ReparsePoint ) ) ;
1387+ Assert . That ( File . ResolveLinkTarget ( tempSource , false ) . FullName , Is . EqualTo ( tempDestination2 ) ) ;
1388+ Assert . True ( Util . IsSymbolicLink ( tempSource ) ) ;
1389+
1390+ // Validate noop when the symbolic link is already up to date
1391+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSource , tempDestination2 , false ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . AlreadyUpToDate ) ) ;
1392+
1393+ // Validate with alt directory separator char
1394+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSource . Replace ( Path . DirectorySeparatorChar , Path . AltDirectorySeparatorChar ) , tempDestination2 , false ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . AlreadyUpToDate ) ) ;
1395+
1396+ // Validate with relative path
1397+ Assert . That ( Util . CreateOrUpdateSymbolicLink ( tempSourceRelative , tempDestination2 , false ) , Is . EqualTo ( Util . CreateOrUpdateSymbolicLinkResult . AlreadyUpToDate ) ) ;
1398+ }
1399+ finally
1400+ {
1401+ try { Directory . Delete ( tempBase , true ) ; } catch { }
13111402 }
13121403 }
13131404
@@ -1321,22 +1412,18 @@ public void CreateSymbolicLinkOnDirectory()
13211412 /// <remark>Implementation of create symbolic links doesn't work on linux so this test is discard on Mono</remark>
13221413 /// </summary>
13231414 [ Test ]
1324- [ Ignore ( "Test Broken" ) ]
13251415 public void IsSymbolicLink ( )
13261416 {
1327- if ( ! Util . IsRunningInMono ( ) )
1328- {
1329- var mockPath1 = Path . GetTempFileName ( ) ;
1330- var mockPath2 = Path . GetTempFileName ( ) ;
1417+ var mockPath1 = Path . GetTempFileName ( ) ;
1418+ var mockPath2 = Path . GetTempFileName ( ) ;
13311419
1332- Assert . False ( Util . IsSymbolicLink ( mockPath1 ) ) ;
1420+ Assert . False ( Util . IsSymbolicLink ( mockPath1 ) ) ;
13331421
1334- Assert . True ( Util . CreateSymbolicLink ( mockPath1 , mockPath2 , false ) ) ;
1335- Assert . True ( Util . IsSymbolicLink ( mockPath1 ) ) ;
1422+ Assert . DoesNotThrow ( ( ) => Util . CreateOrUpdateSymbolicLink ( mockPath1 , mockPath2 , false ) ) ;
1423+ Assert . True ( Util . IsSymbolicLink ( mockPath1 ) ) ;
13361424
1337- File . Delete ( mockPath1 ) ;
1338- File . Delete ( mockPath2 ) ;
1339- }
1425+ File . Delete ( mockPath1 ) ;
1426+ File . Delete ( mockPath2 ) ;
13401427 }
13411428 }
13421429
0 commit comments