diff --git a/ProjectedFSLib.Managed.Test/BasicTests.cs b/ProjectedFSLib.Managed.Test/BasicTests.cs index d64c784..159ba3b 100644 --- a/ProjectedFSLib.Managed.Test/BasicTests.cs +++ b/ProjectedFSLib.Managed.Test/BasicTests.cs @@ -4,12 +4,10 @@ using NUnit.Framework; using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; -using System.Threading; namespace ProjectedFSLib.Managed.Test { @@ -126,6 +124,14 @@ public void TestCanReadThroughVirtualizationRoot(string destinationFile) Assert.That("RandomNonsense", Is.Not.EqualTo(line)); } +#if NETCOREAPP3_1_OR_GREATER + // Running this test in NET framework causes CI failures in the Win 2022 version. + // They fail because the .NET Framework 4.8 version of the fixed Simple provider trips over the platform bug. + // The .NET Core 3.1 one works fine. Evidently Framework and Core enumerate differently, with Framework using + // a buffer that is small enough to hit the platform bug. + // + // The CI Win 2019 version doesn't run the symlink tests at all, since symlink support isn't in that version of ProjFS. + // We start the virtualization instance in each test case, so that exercises the following // methods in Microsoft.Windows.ProjFS: // VirtualizationInstance.VirtualizationInstance() @@ -197,37 +203,30 @@ public void TestCanReadSymlinksThroughVirtualizationRoot(string destinationFile, // IRequiredCallbacks.StartDirectoryEnumeration() // IRequiredCallbacks.GetDirectoryEnumeration() // IRequiredCallbacks.EndDirectoryEnumeration() - [TestCase("dir1\\dir2\\dir3\\sourcebar.txt", "dir4\\dir5\\dir6\\symbar.txt", "..\\..\\..\\dir1\\dir2\\dir3\\sourcebar.txt", Category = SymlinkTestCategory)] - public void TestCanReadSymlinksWithRelativePathTargetsThroughVirtualizationRoot(string destinationFile, string symlinkFile, string symlinkTarget) + [TestCase("dir1\\dir2\\dir3\\", "file.txt", "dir4\\dir5\\sdir6", Category = SymlinkTestCategory)] + public void TestCanReadSymlinkDirsThroughVirtualizationRoot(string destinationDir, string destinationFileName, string symlinkDir) { helpers.StartTestProvider(out string sourceRoot, out string virtRoot); + // Some contents to write to the file in the source and read out through the virtualization. - string fileContent = nameof(TestCanReadSymlinksThroughVirtualizationRoot); + string fileContent = nameof(TestCanReadSymlinkDirsThroughVirtualizationRoot); - // Create a file and a symlink to it. + string destinationFile = Path.Combine(destinationDir, destinationFileName); helpers.CreateVirtualFile(destinationFile, fileContent); - helpers.CreateVirtualSymlink(symlinkFile, symlinkTarget, false); - - // Open the file through the virtualization and read its contents. - string line = helpers.ReadFileInVirtRoot(destinationFile); - Assert.That(fileContent, Is.EqualTo(line)); + helpers.CreateVirtualSymlinkDirectory(symlinkDir, destinationDir, true); // Enumerate and ensure the symlink is present. - var pathToEnumerate = Path.Combine(virtRoot, Path.GetDirectoryName(symlinkFile)); + var pathToEnumerate = Path.Combine(virtRoot, Path.GetDirectoryName(symlinkDir)); DirectoryInfo virtDirInfo = new DirectoryInfo(pathToEnumerate); List virtList = new List(virtDirInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories)); - string fullPath = Path.Combine(virtRoot, symlinkFile); - FileSystemInfo symlink = virtList.Where(x => x.FullName == fullPath).First(); - Assert.That((symlink.Attributes & FileAttributes.ReparsePoint) != 0); - - // Get the symlink target and check that it points to the correct file. - string reparsePointTarget = helpers.ReadReparsePointTargetInVirtualRoot(symlinkFile); - Assert.That(reparsePointTarget, Is.EqualTo(symlinkTarget)); + string fullPath = Path.Combine(virtRoot, symlinkDir); - // Check if we have the same content if accessing the file through a symlink. + // Ensure we can access the file through directory symlink. + string symlinkFile = Path.Combine(virtRoot, symlinkDir, destinationFileName); string lineAccessedThroughSymlink = helpers.ReadFileInVirtRoot(symlinkFile); Assert.That(fileContent, Is.EqualTo(lineAccessedThroughSymlink)); } +#endif // We start the virtualization instance in each test case, so that exercises the following // methods in Microsoft.Windows.ProjFS: @@ -247,26 +246,34 @@ public void TestCanReadSymlinksWithRelativePathTargetsThroughVirtualizationRoot( // IRequiredCallbacks.StartDirectoryEnumeration() // IRequiredCallbacks.GetDirectoryEnumeration() // IRequiredCallbacks.EndDirectoryEnumeration() - [TestCase("dir1\\dir2\\dir3\\", "file.txt", "dir4\\dir5\\sdir6", Category = SymlinkTestCategory)] - public void TestCanReadSymlinkDirsThroughVirtualizationRoot(string destinationDir, string destinationFileName, string symlinkDir) + [TestCase("dir1\\dir2\\dir3\\sourcebar.txt", "dir4\\dir5\\dir6\\symbar.txt", "..\\..\\..\\dir1\\dir2\\dir3\\sourcebar.txt", Category = SymlinkTestCategory)] + public void TestCanReadSymlinksWithRelativePathTargetsThroughVirtualizationRoot(string destinationFile, string symlinkFile, string symlinkTarget) { helpers.StartTestProvider(out string sourceRoot, out string virtRoot); - // Some contents to write to the file in the source and read out through the virtualization. - string fileContent = nameof(TestCanReadSymlinkDirsThroughVirtualizationRoot); + string fileContent = nameof(TestCanReadSymlinksWithRelativePathTargetsThroughVirtualizationRoot); - string destinationFile = Path.Combine(destinationDir, destinationFileName); + // Create a file and a symlink to it. helpers.CreateVirtualFile(destinationFile, fileContent); - helpers.CreateVirtualSymlinkDirectory(symlinkDir, destinationDir, true); + helpers.CreateVirtualSymlink(symlinkFile, symlinkTarget, false); + + // Open the file through the virtualization and read its contents. + string line = helpers.ReadFileInVirtRoot(destinationFile); + Assert.That(fileContent, Is.EqualTo(line)); // Enumerate and ensure the symlink is present. - var pathToEnumerate = Path.Combine(virtRoot, Path.GetDirectoryName(symlinkDir)); + var pathToEnumerate = Path.Combine(virtRoot, Path.GetDirectoryName(symlinkFile)); DirectoryInfo virtDirInfo = new DirectoryInfo(pathToEnumerate); List virtList = new List(virtDirInfo.EnumerateFileSystemInfos("*", SearchOption.AllDirectories)); - string fullPath = Path.Combine(virtRoot, symlinkDir); + string fullPath = Path.Combine(virtRoot, symlinkFile); + FileSystemInfo symlink = virtList.Where(x => x.FullName == fullPath).First(); + Assert.That((symlink.Attributes & FileAttributes.ReparsePoint) != 0); - // Ensure we can access the file through directory symlink. - string symlinkFile = Path.Combine(virtRoot, symlinkDir, destinationFileName); + // Get the symlink target and check that it points to the correct file. + string reparsePointTarget = helpers.ReadReparsePointTargetInVirtualRoot(symlinkFile); + Assert.That(reparsePointTarget, Is.EqualTo(symlinkTarget)); + + // Check if we have the same content if accessing the file through a symlink. string lineAccessedThroughSymlink = helpers.ReadFileInVirtRoot(symlinkFile); Assert.That(fileContent, Is.EqualTo(lineAccessedThroughSymlink)); }