public void ExcludeSparseFileSavedAfterRemount(FileSystemRunner fileSystem) { string fileToAdd = this.Enlistment.GetVirtualPathTo(FileToAdd); fileSystem.WriteAllText(fileToAdd, "Contents for the new file"); string fileToUpdate = this.Enlistment.GetVirtualPathTo(FileToUpdate); fileSystem.AppendAllText(fileToUpdate, "// Testing"); string fileToDelete = this.Enlistment.GetVirtualPathTo(FileToDelete); fileSystem.DeleteFile(fileToDelete); string folderToCreate = this.Enlistment.GetVirtualPathTo(FolderToCreate); fileSystem.CreateDirectory(folderToCreate); // Remount this.Enlistment.UnmountGVFS(); this.Enlistment.MountGVFS(); string excludeFile = this.Enlistment.GetVirtualPathTo(ExcludeFilePath); string excludeFileContents = excludeFile.ShouldBeAFile(fileSystem).WithContents(); excludeFileContents.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries) .Where(x => !x.StartsWith("#")) // Exclude comments .OrderBy(x => x) .ShouldMatchInOrder(expectedExcludeFileContents.OrderBy(x => x)); string sparseFile = this.Enlistment.GetVirtualPathTo(SparseCheckoutFilePath); sparseFile.ShouldBeAFile(fileSystem).WithContents() .Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) .Where(x => expectedSparseFileContents.Contains(x)) // Exclude extra entries for files hydrated during test .OrderBy(x => x) .ShouldMatchInOrder(expectedSparseFileContents.OrderBy(x => x)); }
public void ModifiedPathsSavedAfterRemount(FileSystemRunner fileSystem) { string fileToAdd = this.Enlistment.GetVirtualPathTo(FileToAdd); fileSystem.WriteAllText(fileToAdd, "Contents for the new file"); string fileToUpdate = this.Enlistment.GetVirtualPathTo(FileToUpdate); fileSystem.AppendAllText(fileToUpdate, "// Testing"); string fileToDelete = this.Enlistment.GetVirtualPathTo(FileToDelete); fileSystem.DeleteFile(fileToDelete); fileToDelete.ShouldNotExistOnDisk(fileSystem); string fileToRename = this.Enlistment.GetVirtualPathTo(FileToRename); fileSystem.MoveFile(fileToRename, this.Enlistment.GetVirtualPathTo(RenameFileTarget)); string folderToCreate = this.Enlistment.GetVirtualPathTo(FolderToCreate); fileSystem.CreateDirectory(folderToCreate); string folderToRename = this.Enlistment.GetVirtualPathTo(FolderToRename); fileSystem.CreateDirectory(folderToRename); string folderToRenameTarget = this.Enlistment.GetVirtualPathTo(RenameFolderTarget); fileSystem.MoveDirectory(folderToRename, folderToRenameTarget); // Moving the new folder out of the repo will remove it from the modified paths file string folderTargetOutsideSrc = Path.Combine(this.Enlistment.EnlistmentRoot, RenameFolderTarget); folderTargetOutsideSrc.ShouldNotExistOnDisk(fileSystem); fileSystem.MoveDirectory(folderToRenameTarget, folderTargetOutsideSrc); folderTargetOutsideSrc.ShouldBeADirectory(fileSystem); folderToRenameTarget.ShouldNotExistOnDisk(fileSystem); // Moving a file from the .git folder to the working directory should add the file to the modified paths string dotGitfileToAdd = this.Enlistment.GetVirtualPathTo(DotGitFileToCreate); fileSystem.WriteAllText(dotGitfileToAdd, "Contents for the new file in dot git"); fileSystem.MoveFile(dotGitfileToAdd, this.Enlistment.GetVirtualPathTo(RenameNewDotGitFileTarget)); // Move a file from outside of src into src string fileToCreateOutsideRepoPath = Path.Combine(this.Enlistment.EnlistmentRoot, FileToCreateOutsideRepo); fileSystem.WriteAllText(fileToCreateOutsideRepoPath, "Contents for the new file outside of repo"); string fileToCreateOutsideRepoTargetPath = this.Enlistment.GetVirtualPathTo(FileToCreateOutsideRepo); fileToCreateOutsideRepoTargetPath.ShouldNotExistOnDisk(fileSystem); fileSystem.MoveFile(fileToCreateOutsideRepoPath, fileToCreateOutsideRepoTargetPath); fileToCreateOutsideRepoTargetPath.ShouldBeAFile(fileSystem); fileToCreateOutsideRepoPath.ShouldNotExistOnDisk(fileSystem); // Move a folder from outside of src into src string folderToCreateOutsideRepoPath = Path.Combine(this.Enlistment.EnlistmentRoot, FolderToCreateOutsideRepo); fileSystem.CreateDirectory(folderToCreateOutsideRepoPath); folderToCreateOutsideRepoPath.ShouldBeADirectory(fileSystem); string folderToCreateOutsideRepoTargetPath = this.Enlistment.GetVirtualPathTo(FolderToCreateOutsideRepo); folderToCreateOutsideRepoTargetPath.ShouldNotExistOnDisk(fileSystem); fileSystem.MoveDirectory(folderToCreateOutsideRepoPath, folderToCreateOutsideRepoTargetPath); folderToCreateOutsideRepoTargetPath.ShouldBeADirectory(fileSystem); folderToCreateOutsideRepoPath.ShouldNotExistOnDisk(fileSystem); string folderToDeleteFullPath = this.Enlistment.GetVirtualPathTo(FolderToDelete); fileSystem.WriteAllText(Path.Combine(folderToDeleteFullPath, "NewFile.txt"), "Contents for new file"); string newFileToDelete = Path.Combine(folderToDeleteFullPath, "NewFileToDelete.txt"); fileSystem.WriteAllText(newFileToDelete, "Contents for new file"); fileSystem.DeleteFile(newFileToDelete); fileSystem.WriteAllText(Path.Combine(folderToDeleteFullPath, "CreateCommonVersionHeader.bat"), "Changing the file contents"); fileSystem.DeleteFile(Path.Combine(folderToDeleteFullPath, "RunUnitTests.bat")); fileSystem.DeleteDirectory(folderToDeleteFullPath); folderToDeleteFullPath.ShouldNotExistOnDisk(fileSystem); // Remount this.Enlistment.UnmountGVFS(); this.Enlistment.MountGVFS(); this.Enlistment.WaitForBackgroundOperations().ShouldEqual(true, "Background operations failed to complete."); string modifiedPathsDatabase = Path.Combine(this.Enlistment.DotGVFSRoot, TestConstants.Databases.ModifiedPaths); modifiedPathsDatabase.ShouldBeAFile(fileSystem); using (StreamReader reader = new StreamReader(File.Open(modifiedPathsDatabase, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))) { reader.ReadToEnd().Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).OrderBy(x => x) .ShouldMatchInOrder(ExpectedModifiedFilesContentsAfterRemount.OrderBy(x => x)); } }
public void CanReadWriteAFileInParallel(FileSystemRunner fileSystem) { string fileName = @"CanReadWriteAFileInParallel"; string virtualPath = this.Enlistment.GetVirtualPathTo(fileName); // Create the file new each time. virtualPath.ShouldNotExistOnDisk(fileSystem); File.Create(virtualPath).Dispose(); bool keepRunning = true; Thread[] threads = new Thread[4]; StringBuilder[] fileContents = new StringBuilder[4]; Exception writeException = null; // Writer fileContents[0] = new StringBuilder(); threads[0] = new Thread(() => { DateTime start = DateTime.Now; Random r = new Random(0); // Seeded for repeatability while ((DateTime.Now - start).TotalSeconds < 2.5) { string newChar = r.Next(10).ToString(); try { fileSystem.AppendAllText(virtualPath, newChar); fileContents[0].Append(newChar); } catch (IOException) when(Marshal.GetLastWin32Error() == this.nativeEWouldBlock && this.nativeEWouldBlock > 0) { // ignore EAGAIN } catch (Exception e) { writeException = e; } Thread.Yield(); } keepRunning = false; }); Exception readException = null; // Readers for (int i = 1; i < threads.Length; ++i) { int myIndex = i; fileContents[i] = new StringBuilder(); threads[i] = new Thread(() => { bool retry = true; while (retry) { Stream readStream = null; try { readStream = File.Open(virtualPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); retry = false; using (StreamReader reader = new StreamReader(readStream, true)) { while (keepRunning) { Thread.Yield(); fileContents[myIndex].Append(reader.ReadToEnd()); } // Catch the last write that might have escaped us fileContents[myIndex].Append(reader.ReadToEnd()); } } catch (IOException) when(Marshal.GetLastWin32Error() == this.nativeEWouldBlock && this.nativeEWouldBlock > 0) { // ignore EAGAIN } catch (Exception e) { readException = e; retry = false; } finally { if (readStream != null) { ((IDisposable)readStream).Dispose(); } } } }); } foreach (Thread thread in threads) { thread.Start(); } foreach (Thread thread in threads) { thread.Join(); } for (int i = 1; i < threads.Length; ++i) { fileContents[i].ToString().ShouldEqual(fileContents[0].ToString()); } fileSystem.DeleteFile(virtualPath); readException.ShouldBeNull("At least one of the reads failed"); writeException.ShouldBeNull("At least one of the writes failed"); }
public void ExcludeSparseFileSavedAfterRemount(FileSystemRunner fileSystem) { string fileToAdd = this.Enlistment.GetVirtualPathTo(FileToAdd); fileSystem.WriteAllText(fileToAdd, "Contents for the new file"); string fileToUpdate = this.Enlistment.GetVirtualPathTo(FileToUpdate); fileSystem.AppendAllText(fileToUpdate, "// Testing"); string fileToDelete = this.Enlistment.GetVirtualPathTo(FileToDelete); fileSystem.DeleteFile(fileToDelete); string fileToRename = this.Enlistment.GetVirtualPathTo(FileToRename); fileSystem.MoveFile(fileToRename, this.Enlistment.GetVirtualPathTo(RenameFileTarget)); string folderToCreate = this.Enlistment.GetVirtualPathTo(FolderToCreate); fileSystem.CreateDirectory(folderToCreate); string folderToRename = this.Enlistment.GetVirtualPathTo(FolderToRename); fileSystem.CreateDirectory(folderToRename); string folderToRenameTarget = this.Enlistment.GetVirtualPathTo(RenameFolderTarget); fileSystem.MoveDirectory(folderToRename, folderToRenameTarget); // Moving the new folder out of the repo should not change the always exclude file string folderTargetOutsideSrc = Path.Combine(this.Enlistment.EnlistmentRoot, RenameFolderTarget); folderTargetOutsideSrc.ShouldNotExistOnDisk(fileSystem); fileSystem.MoveDirectory(folderToRenameTarget, folderTargetOutsideSrc); folderTargetOutsideSrc.ShouldBeADirectory(fileSystem); // Moving a file from the .git folder to the working directory should add the file to the sparse-checkout string dotGitfileToAdd = this.Enlistment.GetVirtualPathTo(DotGitFileToCreate); fileSystem.WriteAllText(dotGitfileToAdd, "Contents for the new file in dot git"); fileSystem.MoveFile(dotGitfileToAdd, this.Enlistment.GetVirtualPathTo(RenameNewDotGitFileTarget)); // Move a file from outside of src into src string fileToCreateOutsideRepoPath = Path.Combine(this.Enlistment.EnlistmentRoot, FileToCreateOutsideRepo); fileSystem.WriteAllText(fileToCreateOutsideRepoPath, "Contents for the new file outside of repo"); string fileToCreateOutsideRepoTargetPath = this.Enlistment.GetVirtualPathTo(FileToCreateOutsideRepo); fileToCreateOutsideRepoTargetPath.ShouldNotExistOnDisk(fileSystem); fileSystem.MoveFile(fileToCreateOutsideRepoPath, fileToCreateOutsideRepoTargetPath); fileToCreateOutsideRepoTargetPath.ShouldBeAFile(fileSystem); // Move a folder from outside of src into src string folderToCreateOutsideRepoPath = Path.Combine(this.Enlistment.EnlistmentRoot, FolderToCreateOutsideRepo); fileSystem.CreateDirectory(folderToCreateOutsideRepoPath); folderToCreateOutsideRepoPath.ShouldBeADirectory(fileSystem); string folderToCreateOutsideRepoTargetPath = this.Enlistment.GetVirtualPathTo(FolderToCreateOutsideRepo); folderToCreateOutsideRepoTargetPath.ShouldNotExistOnDisk(fileSystem); fileSystem.MoveDirectory(folderToCreateOutsideRepoPath, folderToCreateOutsideRepoTargetPath); folderToCreateOutsideRepoTargetPath.ShouldBeADirectory(fileSystem); // Remount this.Enlistment.UnmountGVFS(); this.Enlistment.MountGVFS(); this.Enlistment.WaitForBackgroundOperations().ShouldEqual(true, "Background operations failed to complete."); string alwaysExcludeFile = this.Enlistment.GetVirtualPathTo(AlwaysExcludeFilePath); string alwaysExcludeFileContents = alwaysExcludeFile.ShouldBeAFile(fileSystem).WithContents(); alwaysExcludeFileContents.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries) .Where(x => !x.StartsWith("#")) // Exclude comments .OrderBy(x => x) .ShouldMatchInOrder(expectedAlwaysExcludeFileContents.OrderBy(x => x)); string sparseFile = this.Enlistment.GetVirtualPathTo(SparseCheckoutFilePath); string sparseFileContents = sparseFile.ShouldBeAFile(fileSystem).WithContents(); sparseFileContents.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) .Where(x => expectedSparseFileContents.Contains(x)) // Exclude extra entries for files hydrated during test .OrderBy(x => x) .ShouldMatchInOrder(expectedSparseFileContents.OrderBy(x => x)); }
public void CanReadWriteAFileInParallel(FileSystemRunner fileSystem) { string fileName = @"CanReadWriteAFileInParallel"; string virtualPath = this.Enlistment.GetVirtualPathTo(fileName); // Create the file new each time. virtualPath.ShouldNotExistOnDisk(fileSystem); File.Create(virtualPath).Dispose(); bool keepRunning = true; Thread[] threads = new Thread[4]; StringBuilder[] fileContents = new StringBuilder[4]; // Writer fileContents[0] = new StringBuilder(); threads[0] = new Thread(() => { DateTime start = DateTime.Now; Random r = new Random(0); // Seeded for repeatability while ((DateTime.Now - start).TotalSeconds < 2.5) { string newChar = r.Next(10).ToString(); fileSystem.AppendAllText(virtualPath, newChar); fileContents[0].Append(newChar); Thread.Yield(); } keepRunning = false; }); // Readers for (int i = 1; i < threads.Length; ++i) { int myIndex = i; fileContents[i] = new StringBuilder(); threads[i] = new Thread(() => { using (Stream readStream = File.Open(virtualPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (StreamReader reader = new StreamReader(readStream, true)) { while (keepRunning) { Thread.Yield(); fileContents[myIndex].Append(reader.ReadToEnd()); } // Catch the last write that might have escaped us fileContents[myIndex].Append(reader.ReadToEnd()); } }); } foreach (Thread thread in threads) { thread.Start(); } foreach (Thread thread in threads) { thread.Join(); } for (int i = 1; i < threads.Length; ++i) { fileContents[i].ToString().ShouldEqual(fileContents[0].ToString()); } fileSystem.DeleteFile(virtualPath); }
public void ExcludeSparseFileSavedAfterRemount(FileSystemRunner fileSystem) { string fileToAdd = this.Enlistment.GetVirtualPathTo(FileToAdd); fileSystem.WriteAllText(fileToAdd, "Contents for the new file"); string fileToUpdate = this.Enlistment.GetVirtualPathTo(FileToUpdate); fileSystem.AppendAllText(fileToUpdate, "// Testing"); string fileToDelete = this.Enlistment.GetVirtualPathTo(FileToDelete); fileSystem.DeleteFile(fileToDelete); fileToDelete.ShouldNotExistOnDisk(fileSystem); string fileToRename = this.Enlistment.GetVirtualPathTo(FileToRename); fileSystem.MoveFile(fileToRename, this.Enlistment.GetVirtualPathTo(RenameFileTarget)); string folderToCreate = this.Enlistment.GetVirtualPathTo(FolderToCreate); fileSystem.CreateDirectory(folderToCreate); string folderToRename = this.Enlistment.GetVirtualPathTo(FolderToRename); fileSystem.CreateDirectory(folderToRename); string folderToRenameTarget = this.Enlistment.GetVirtualPathTo(RenameFolderTarget); fileSystem.MoveDirectory(folderToRename, folderToRenameTarget); // Moving the new folder out of the repo should not change the always_exclude file string folderTargetOutsideSrc = Path.Combine(this.Enlistment.EnlistmentRoot, RenameFolderTarget); folderTargetOutsideSrc.ShouldNotExistOnDisk(fileSystem); fileSystem.MoveDirectory(folderToRenameTarget, folderTargetOutsideSrc); folderTargetOutsideSrc.ShouldBeADirectory(fileSystem); folderToRenameTarget.ShouldNotExistOnDisk(fileSystem); // Moving a file from the .git folder to the working directory should add the file to the sparse-checkout string dotGitfileToAdd = this.Enlistment.GetVirtualPathTo(DotGitFileToCreate); fileSystem.WriteAllText(dotGitfileToAdd, "Contents for the new file in dot git"); fileSystem.MoveFile(dotGitfileToAdd, this.Enlistment.GetVirtualPathTo(RenameNewDotGitFileTarget)); // Move a file from outside of src into src string fileToCreateOutsideRepoPath = Path.Combine(this.Enlistment.EnlistmentRoot, FileToCreateOutsideRepo); fileSystem.WriteAllText(fileToCreateOutsideRepoPath, "Contents for the new file outside of repo"); string fileToCreateOutsideRepoTargetPath = this.Enlistment.GetVirtualPathTo(FileToCreateOutsideRepo); fileToCreateOutsideRepoTargetPath.ShouldNotExistOnDisk(fileSystem); fileSystem.MoveFile(fileToCreateOutsideRepoPath, fileToCreateOutsideRepoTargetPath); fileToCreateOutsideRepoTargetPath.ShouldBeAFile(fileSystem); fileToCreateOutsideRepoPath.ShouldNotExistOnDisk(fileSystem); // Move a folder from outside of src into src string folderToCreateOutsideRepoPath = Path.Combine(this.Enlistment.EnlistmentRoot, FolderToCreateOutsideRepo); fileSystem.CreateDirectory(folderToCreateOutsideRepoPath); folderToCreateOutsideRepoPath.ShouldBeADirectory(fileSystem); string folderToCreateOutsideRepoTargetPath = this.Enlistment.GetVirtualPathTo(FolderToCreateOutsideRepo); folderToCreateOutsideRepoTargetPath.ShouldNotExistOnDisk(fileSystem); fileSystem.MoveDirectory(folderToCreateOutsideRepoPath, folderToCreateOutsideRepoTargetPath); folderToCreateOutsideRepoTargetPath.ShouldBeADirectory(fileSystem); folderToCreateOutsideRepoPath.ShouldNotExistOnDisk(fileSystem); string folderToDelete = this.Enlistment.GetVirtualPathTo(FolderToDelete); fileSystem.DeleteDirectory(folderToDelete); folderToDelete.ShouldNotExistOnDisk(fileSystem); // Remount this.Enlistment.UnmountGVFS(); this.Enlistment.MountGVFS(); this.Enlistment.WaitForBackgroundOperations().ShouldEqual(true, "Background operations failed to complete."); string modifiedPathsDatabase = Path.Combine(this.Enlistment.DotGVFSRoot, TestConstants.Databases.ModifiedPaths); modifiedPathsDatabase.ShouldBeAFile(fileSystem); using (StreamReader reader = new StreamReader(File.Open(modifiedPathsDatabase, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))) { reader.ReadToEnd().ShouldEqual(ExpectedModifiedFilesContents); } }
public void ModifiedPathsFromChangesInsideRepoSavedAfterRemount(FileSystemRunner fileSystem) { string[] expectedModifiedFilesContentsAfterRemount = { @"A .gitattributes", $"A {GVFSHelpers.ConvertPathToGitFormat(FileToAdd)}", $"A {GVFSHelpers.ConvertPathToGitFormat(FileToUpdate)}", $"A {FileToDelete}", $"A {GVFSHelpers.ConvertPathToGitFormat(FileToRename)}", $"A {GVFSHelpers.ConvertPathToGitFormat(RenameFileTarget)}", $"A {FolderToCreate}/", $"A {RenameNewDotGitFileTarget}", $"A {FolderToDelete}/", }; string fileToAdd = this.Enlistment.GetVirtualPathTo(FileToAdd); fileSystem.WriteAllText(fileToAdd, "Contents for the new file"); string fileToUpdate = this.Enlistment.GetVirtualPathTo(FileToUpdate); fileSystem.AppendAllText(fileToUpdate, "// Testing"); string fileToDelete = this.Enlistment.GetVirtualPathTo(FileToDelete); fileSystem.DeleteFile(fileToDelete); fileToDelete.ShouldNotExistOnDisk(fileSystem); string fileToRename = this.Enlistment.GetVirtualPathTo(FileToRename); fileSystem.MoveFile(fileToRename, this.Enlistment.GetVirtualPathTo(RenameFileTarget)); string folderToCreate = this.Enlistment.GetVirtualPathTo(FolderToCreate); fileSystem.CreateDirectory(folderToCreate); string folderToRename = this.Enlistment.GetVirtualPathTo(FolderToRename); fileSystem.CreateDirectory(folderToRename); string folderToRenameTarget = this.Enlistment.GetVirtualPathTo(RenameFolderTarget); fileSystem.MoveDirectory(folderToRename, folderToRenameTarget); // Deleting the new folder will remove it from the modified paths file fileSystem.DeleteDirectory(folderToRenameTarget); folderToRenameTarget.ShouldNotExistOnDisk(fileSystem); // Moving a file from the .git folder to the working directory should add the file to the modified paths string dotGitfileToAdd = this.Enlistment.GetVirtualPathTo(DotGitFileToCreate); fileSystem.WriteAllText(dotGitfileToAdd, "Contents for the new file in dot git"); fileSystem.MoveFile(dotGitfileToAdd, this.Enlistment.GetVirtualPathTo(RenameNewDotGitFileTarget)); string folderToDeleteFullPath = this.Enlistment.GetVirtualPathTo(FolderToDelete); fileSystem.WriteAllText(Path.Combine(folderToDeleteFullPath, "NewFile.txt"), "Contents for new file"); string newFileToDelete = Path.Combine(folderToDeleteFullPath, "NewFileToDelete.txt"); fileSystem.WriteAllText(newFileToDelete, "Contents for new file"); fileSystem.DeleteFile(newFileToDelete); fileSystem.WriteAllText(Path.Combine(folderToDeleteFullPath, "CreateCommonVersionHeader.bat"), "Changing the file contents"); fileSystem.DeleteFile(Path.Combine(folderToDeleteFullPath, "RunUnitTests.bat")); fileSystem.DeleteDirectory(folderToDeleteFullPath); folderToDeleteFullPath.ShouldNotExistOnDisk(fileSystem); // Remount this.Enlistment.UnmountGVFS(); this.Enlistment.MountGVFS(); this.Enlistment.WaitForBackgroundOperations(); string modifiedPathsDatabase = Path.Combine(this.Enlistment.DotGVFSRoot, TestConstants.Databases.ModifiedPaths); modifiedPathsDatabase.ShouldBeAFile(fileSystem); using (StreamReader reader = new StreamReader(File.Open(modifiedPathsDatabase, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))) { reader.ReadToEnd().Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).OrderBy(x => x) .ShouldMatchInOrder(expectedModifiedFilesContentsAfterRemount.OrderBy(x => x)); } }