44using NUnit . Framework ;
55using System ;
66using System . Collections . Generic ;
7- using System . Diagnostics ;
87using System . IO ;
98using System . Linq ;
109using System . Runtime . InteropServices ;
1110using System . Text ;
12- using System . Threading ;
1311
1412namespace ProjectedFSLib . Managed . Test
1513{
@@ -126,6 +124,14 @@ public void TestCanReadThroughVirtualizationRoot(string destinationFile)
126124 Assert . That ( "RandomNonsense" , Is . Not . EqualTo ( line ) ) ;
127125 }
128126
127+ #if NETCOREAPP3_1_OR_GREATER
128+ // Running this test in NET framework causes CI failures in the Win 2022 version.
129+ // They fail because the .NET Framework 4.8 version of the fixed Simple provider trips over the platform bug.
130+ // The .NET Core 3.1 one works fine. Evidently Framework and Core enumerate differently, with Framework using
131+ // a buffer that is small enough to hit the platform bug.
132+ //
133+ // The CI Win 2019 version doesn't run the symlink tests at all, since symlink support isn't in that version of ProjFS.
134+
129135 // We start the virtualization instance in each test case, so that exercises the following
130136 // methods in Microsoft.Windows.ProjFS:
131137 // VirtualizationInstance.VirtualizationInstance()
@@ -197,37 +203,30 @@ public void TestCanReadSymlinksThroughVirtualizationRoot(string destinationFile,
197203 // IRequiredCallbacks.StartDirectoryEnumeration()
198204 // IRequiredCallbacks.GetDirectoryEnumeration()
199205 // IRequiredCallbacks.EndDirectoryEnumeration()
200- [ TestCase ( "dir1\\ dir2\\ dir3\\ sourcebar.txt " , "dir4 \\ dir5 \\ dir6 \\ symbar .txt" , ".. \\ .. \\ .. \\ dir1 \\ dir2 \\ dir3 \\ sourcebar.txt " , Category = SymlinkTestCategory ) ]
201- public void TestCanReadSymlinksWithRelativePathTargetsThroughVirtualizationRoot ( string destinationFile , string symlinkFile , string symlinkTarget )
206+ [ TestCase ( "dir1\\ dir2\\ dir3\\ " , "file .txt" , "dir4 \\ dir5 \\ sdir6 " , Category = SymlinkTestCategory ) ]
207+ public void TestCanReadSymlinkDirsThroughVirtualizationRoot ( string destinationDir , string destinationFileName , string symlinkDir )
202208 {
203209 helpers . StartTestProvider ( out string sourceRoot , out string virtRoot ) ;
210+
204211 // Some contents to write to the file in the source and read out through the virtualization.
205- string fileContent = nameof ( TestCanReadSymlinksThroughVirtualizationRoot ) ;
212+ string fileContent = nameof ( TestCanReadSymlinkDirsThroughVirtualizationRoot ) ;
206213
207- // Create a file and a symlink to it.
214+ string destinationFile = Path . Combine ( destinationDir , destinationFileName ) ;
208215 helpers . CreateVirtualFile ( destinationFile , fileContent ) ;
209- helpers . CreateVirtualSymlink ( symlinkFile , symlinkTarget , false ) ;
210-
211- // Open the file through the virtualization and read its contents.
212- string line = helpers . ReadFileInVirtRoot ( destinationFile ) ;
213- Assert . That ( fileContent , Is . EqualTo ( line ) ) ;
216+ helpers . CreateVirtualSymlinkDirectory ( symlinkDir , destinationDir , true ) ;
214217
215218 // Enumerate and ensure the symlink is present.
216- var pathToEnumerate = Path . Combine ( virtRoot , Path . GetDirectoryName ( symlinkFile ) ) ;
219+ var pathToEnumerate = Path . Combine ( virtRoot , Path . GetDirectoryName ( symlinkDir ) ) ;
217220 DirectoryInfo virtDirInfo = new DirectoryInfo ( pathToEnumerate ) ;
218221 List < FileSystemInfo > virtList = new List < FileSystemInfo > ( virtDirInfo . EnumerateFileSystemInfos ( "*" , SearchOption . AllDirectories ) ) ;
219- string fullPath = Path . Combine ( virtRoot , symlinkFile ) ;
220- FileSystemInfo symlink = virtList . Where ( x => x . FullName == fullPath ) . First ( ) ;
221- Assert . That ( ( symlink . Attributes & FileAttributes . ReparsePoint ) != 0 ) ;
222-
223- // Get the symlink target and check that it points to the correct file.
224- string reparsePointTarget = helpers . ReadReparsePointTargetInVirtualRoot ( symlinkFile ) ;
225- Assert . That ( reparsePointTarget , Is . EqualTo ( symlinkTarget ) ) ;
222+ string fullPath = Path . Combine ( virtRoot , symlinkDir ) ;
226223
227- // Check if we have the same content if accessing the file through a symlink.
224+ // Ensure we can access the file through directory symlink.
225+ string symlinkFile = Path . Combine ( virtRoot , symlinkDir , destinationFileName ) ;
228226 string lineAccessedThroughSymlink = helpers . ReadFileInVirtRoot ( symlinkFile ) ;
229227 Assert . That ( fileContent , Is . EqualTo ( lineAccessedThroughSymlink ) ) ;
230228 }
229+ #endif
231230
232231 // We start the virtualization instance in each test case, so that exercises the following
233232 // methods in Microsoft.Windows.ProjFS:
@@ -247,26 +246,34 @@ public void TestCanReadSymlinksWithRelativePathTargetsThroughVirtualizationRoot(
247246 // IRequiredCallbacks.StartDirectoryEnumeration()
248247 // IRequiredCallbacks.GetDirectoryEnumeration()
249248 // IRequiredCallbacks.EndDirectoryEnumeration()
250- [ TestCase ( "dir1\\ dir2\\ dir3\\ " , "file .txt" , "dir4 \\ dir5 \\ sdir6 " , Category = SymlinkTestCategory ) ]
251- public void TestCanReadSymlinkDirsThroughVirtualizationRoot ( string destinationDir , string destinationFileName , string symlinkDir )
249+ [ TestCase ( "dir1\\ dir2\\ dir3\\ sourcebar.txt " , "dir4 \\ dir5 \\ dir6 \\ symbar .txt" , ".. \\ .. \\ .. \\ dir1 \\ dir2 \\ dir3 \\ sourcebar.txt " , Category = SymlinkTestCategory ) ]
250+ public void TestCanReadSymlinksWithRelativePathTargetsThroughVirtualizationRoot ( string destinationFile , string symlinkFile , string symlinkTarget )
252251 {
253252 helpers . StartTestProvider ( out string sourceRoot , out string virtRoot ) ;
254-
255253 // Some contents to write to the file in the source and read out through the virtualization.
256- string fileContent = nameof ( TestCanReadSymlinkDirsThroughVirtualizationRoot ) ;
254+ string fileContent = nameof ( TestCanReadSymlinksWithRelativePathTargetsThroughVirtualizationRoot ) ;
257255
258- string destinationFile = Path . Combine ( destinationDir , destinationFileName ) ;
256+ // Create a file and a symlink to it.
259257 helpers . CreateVirtualFile ( destinationFile , fileContent ) ;
260- helpers . CreateVirtualSymlinkDirectory ( symlinkDir , destinationDir , true ) ;
258+ helpers . CreateVirtualSymlink ( symlinkFile , symlinkTarget , false ) ;
259+
260+ // Open the file through the virtualization and read its contents.
261+ string line = helpers . ReadFileInVirtRoot ( destinationFile ) ;
262+ Assert . That ( fileContent , Is . EqualTo ( line ) ) ;
261263
262264 // Enumerate and ensure the symlink is present.
263- var pathToEnumerate = Path . Combine ( virtRoot , Path . GetDirectoryName ( symlinkDir ) ) ;
265+ var pathToEnumerate = Path . Combine ( virtRoot , Path . GetDirectoryName ( symlinkFile ) ) ;
264266 DirectoryInfo virtDirInfo = new DirectoryInfo ( pathToEnumerate ) ;
265267 List < FileSystemInfo > virtList = new List < FileSystemInfo > ( virtDirInfo . EnumerateFileSystemInfos ( "*" , SearchOption . AllDirectories ) ) ;
266- string fullPath = Path . Combine ( virtRoot , symlinkDir ) ;
268+ string fullPath = Path . Combine ( virtRoot , symlinkFile ) ;
269+ FileSystemInfo symlink = virtList . Where ( x => x . FullName == fullPath ) . First ( ) ;
270+ Assert . That ( ( symlink . Attributes & FileAttributes . ReparsePoint ) != 0 ) ;
267271
268- // Ensure we can access the file through directory symlink.
269- string symlinkFile = Path . Combine ( virtRoot , symlinkDir , destinationFileName ) ;
272+ // Get the symlink target and check that it points to the correct file.
273+ string reparsePointTarget = helpers . ReadReparsePointTargetInVirtualRoot ( symlinkFile ) ;
274+ Assert . That ( reparsePointTarget , Is . EqualTo ( symlinkTarget ) ) ;
275+
276+ // Check if we have the same content if accessing the file through a symlink.
270277 string lineAccessedThroughSymlink = helpers . ReadFileInVirtRoot ( symlinkFile ) ;
271278 Assert . That ( fileContent , Is . EqualTo ( lineAccessedThroughSymlink ) ) ;
272279 }
0 commit comments