public void GetMetadataForHeartBeatDoesNotChangeEventLevelWhenNoPlaceholderHaveBeenCreated() { Mock <IPlaceholderCollection> mockPlaceholderDb = new Mock <IPlaceholderCollection>(MockBehavior.Strict); mockPlaceholderDb.Setup(x => x.GetCount()).Returns(0); mockPlaceholderDb.Setup(x => x.GetFilePlaceholdersCount()).Returns(() => 0); mockPlaceholderDb.Setup(x => x.GetFolderPlaceholdersCount()).Returns(() => 0); Mock <ISparseCollection> mockSparseDb = new Mock <ISparseCollection>(MockBehavior.Strict); mockSparseDb.Setup(x => x.GetAll()).Returns(new HashSet <string>()); using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: null, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: null, placeholderDatabase: mockPlaceholderDb.Object, sparseCollection: mockSparseDb.Object)) { EventMetadata metadata = fileSystemCallbacks.GetAndResetHeartBeatMetadata(out bool writeToLogFile); EventLevel eventLevel = writeToLogFile ? EventLevel.Informational : EventLevel.Verbose; eventLevel.ShouldEqual(EventLevel.Verbose); // "ModifiedPathsCount" should be 1 because ".gitattributes" is always present metadata.ShouldContain("ModifiedPathsCount", 1); metadata.ShouldContain("FilePlaceholderCount", 0); metadata.ShouldContain(nameof(RepoMetadata.Instance.EnlistmentId), RepoMetadata.Instance.EnlistmentId); } mockPlaceholderDb.VerifyAll(); mockSparseDb.VerifyAll(); }
protected void OnFileRenamed(string relativeSourcePath, string relativeDestinationPath, bool isDirectory) { try { bool srcPathInDotGit = FileSystemCallbacks.IsPathInsideDotGit(relativeSourcePath); bool dstPathInDotGit = FileSystemCallbacks.IsPathInsideDotGit(relativeDestinationPath); if (dstPathInDotGit) { this.OnDotGitFileOrFolderChanged(relativeDestinationPath); } if (!(srcPathInDotGit && dstPathInDotGit)) { if (isDirectory) { this.FileSystemCallbacks.OnFolderRenamed(relativeSourcePath, relativeDestinationPath); } else { this.FileSystemCallbacks.OnFileRenamed(relativeSourcePath, relativeDestinationPath); } } } catch (Exception e) { EventMetadata metadata = this.CreateEventMetadata(relativeSourcePath, e); metadata.Add("destinationPath", relativeDestinationPath); metadata.Add("isDirectory", isDirectory); this.LogUnhandledExceptionAndExit(nameof(this.OnFileRenamed), metadata); } }
public void OnEnumerateDirectorySetsFileModes() { using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockVirtualizationInstance mockVirtualization = new MockVirtualizationInstance()) using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { "test644.txt", "test664.txt", "test755.txt" })) using (MacFileSystemVirtualizer virtualizer = new MacFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects, mockVirtualization)) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: virtualizer)) { gitIndexProjection.MockFileModes.TryAdd("test" + Path.DirectorySeparatorChar + "test644.txt", FileMode644); gitIndexProjection.MockFileModes.TryAdd("test" + Path.DirectorySeparatorChar + "test664.txt", FileMode664); gitIndexProjection.MockFileModes.TryAdd("test" + Path.DirectorySeparatorChar + "test755.txt", FileMode755); string error; fileSystemCallbacks.TryStart(out error).ShouldEqual(true); Guid enumerationGuid = Guid.NewGuid(); gitIndexProjection.EnumerationInMemory = true; mockVirtualization.OnEnumerateDirectory(1, "test", triggeringProcessId: 1, triggeringProcessName: "UnitTests").ShouldEqual(Result.Success); mockVirtualization.CreatedPlaceholders.ShouldContain( kvp => kvp.Key.Equals(Path.Combine("test", "test644.txt"), StringComparison.OrdinalIgnoreCase) && kvp.Value == FileMode644); mockVirtualization.CreatedPlaceholders.ShouldContain( kvp => kvp.Key.Equals(Path.Combine("test", "test664.txt"), StringComparison.OrdinalIgnoreCase) && kvp.Value == FileMode664); mockVirtualization.CreatedPlaceholders.ShouldContain( kvp => kvp.Key.Equals(Path.Combine("test", "test755.txt"), StringComparison.OrdinalIgnoreCase) && kvp.Value == FileMode755); fileSystemCallbacks.Stop(); } }
public void TestFileSystemOperationsInvalidateStatusCache() { Mock <IPlaceholderCollection> mockPlaceholderDb = new Mock <IPlaceholderCollection>(MockBehavior.Strict); mockPlaceholderDb.Setup(x => x.GetCount()).Returns(1); using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockFileSystemVirtualizer fileSystemVirtualizer = new MockFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects)) using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { "test.txt" })) using (MockGitStatusCache gitStatusCache = new MockGitStatusCache(this.Repo.Context, TimeSpan.Zero)) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: gitIndexProjection, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: fileSystemVirtualizer, placeholderDatabase: mockPlaceholderDb.Object, gitStatusCache: gitStatusCache)) { this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileConvertedToFull, "OnFileConvertedToFull.txt", FileSystemTask.OperationType.OnFileConvertedToFull); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileCreated, "OnFileCreated.txt", FileSystemTask.OperationType.OnFileCreated); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileDeleted, "OnFileDeleted.txt", FileSystemTask.OperationType.OnFileDeleted); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileOverwritten, "OnFileDeleted.txt", FileSystemTask.OperationType.OnFileOverwritten); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileSuperseded, "OnFileSuperseded.txt", FileSystemTask.OperationType.OnFileSuperseded); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFolderCreated, "OnFileSuperseded.txt", FileSystemTask.OperationType.OnFolderCreated); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFolderDeleted, "OnFileSuperseded.txt", FileSystemTask.OperationType.OnFolderDeleted); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileConvertedToFull, "OnFileConvertedToFull.txt", FileSystemTask.OperationType.OnFileConvertedToFull); } mockPlaceholderDb.VerifyAll(); }
public void BackgroundOperationCountMatchesBackgroundFileSystemTaskRunner() { Mock <IPlaceholderCollection> mockPlaceholderDb = new Mock <IPlaceholderCollection>(MockBehavior.Strict); mockPlaceholderDb.Setup(x => x.GetCount()).Returns(1); Mock <ISparseCollection> mockSparseDb = new Mock <ISparseCollection>(MockBehavior.Strict); mockSparseDb.Setup(x => x.GetAll()).Returns(new HashSet <string>()); using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: null, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: null, placeholderDatabase: mockPlaceholderDb.Object, sparseCollection: mockSparseDb.Object)) { fileSystemCallbacks.BackgroundOperationCount.ShouldEqual(backgroundTaskRunner.Count); fileSystemCallbacks.OnFileConvertedToFull("Path1.txt"); fileSystemCallbacks.OnFileConvertedToFull("Path2.txt"); backgroundTaskRunner.Count.ShouldEqual(2); fileSystemCallbacks.BackgroundOperationCount.ShouldEqual(backgroundTaskRunner.Count); } mockPlaceholderDb.VerifyAll(); mockSparseDb.VerifyAll(); }
protected void OnHardLinkCreated(string relativeExistingFilePath, string relativeNewLinkPath) { try { if (!string.IsNullOrEmpty(relativeNewLinkPath)) { bool pathInDotGit = FileSystemCallbacks.IsPathInsideDotGit(relativeNewLinkPath); if (pathInDotGit) { this.OnDotGitFileOrFolderChanged(relativeNewLinkPath); } else { this.FileSystemCallbacks.OnFileHardLinkCreated(relativeNewLinkPath); } } } catch (Exception e) { EventMetadata metadata = this.CreateEventMetadata(relativeNewLinkPath, e); metadata.Add(nameof(relativeExistingFilePath), relativeExistingFilePath); this.LogUnhandledExceptionAndExit(nameof(this.OnHardLinkCreated), metadata); } }
public void OnEnumerateDirectorySetsFileModes() { const string TestFile644Name = "test644.txt"; const string TestFile664Name = "test664.txt"; const string TestFile755Name = "test755.txt"; const string TestFolderName = "testFolder"; string testFile644Path = Path.Combine(TestFolderName, TestFile644Name); string testFile664Path = Path.Combine(TestFolderName, TestFile664Name); string testFile755Path = Path.Combine(TestFolderName, TestFile755Name); Mock <IPlaceholderCollection> mockPlaceholderDb = new Mock <IPlaceholderCollection>(MockBehavior.Strict); mockPlaceholderDb.Setup(x => x.GetCount()).Returns(1); Mock <ISparseCollection> mockSparseDb = new Mock <ISparseCollection>(MockBehavior.Strict); using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockVirtualizationInstance mockVirtualization = new MockVirtualizationInstance()) // Don't include TestFolderName as MockGitIndexProjection returns the same list of files regardless of what folder name // it is passed using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { TestFile644Name, TestFile664Name, TestFile755Name })) using (MacFileSystemVirtualizer virtualizer = new MacFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects, mockVirtualization)) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection, backgroundTaskRunner, virtualizer, mockPlaceholderDb.Object, mockSparseDb.Object)) { gitIndexProjection.MockFileTypesAndModes.TryAdd( testFile644Path, ConvertFileTypeAndModeToIndexFormat(GitIndexProjection.FileType.Regular, GitIndexProjection.FileMode644)); gitIndexProjection.MockFileTypesAndModes.TryAdd( testFile664Path, ConvertFileTypeAndModeToIndexFormat(GitIndexProjection.FileType.Regular, GitIndexProjection.FileMode664)); gitIndexProjection.MockFileTypesAndModes.TryAdd( testFile755Path, ConvertFileTypeAndModeToIndexFormat(GitIndexProjection.FileType.Regular, GitIndexProjection.FileMode755)); string error; fileSystemCallbacks.TryStart(out error).ShouldEqual(true); Guid enumerationGuid = Guid.NewGuid(); gitIndexProjection.EnumerationInMemory = true; mockVirtualization.OnEnumerateDirectory(1, TestFolderName, triggeringProcessId: 1, triggeringProcessName: "UnitTests").ShouldEqual(Result.Success); mockVirtualization.CreatedPlaceholders.ShouldContain( kvp => kvp.Key.Equals(testFile644Path, StringComparison.OrdinalIgnoreCase) && kvp.Value == GitIndexProjection.FileMode644); mockVirtualization.CreatedPlaceholders.ShouldContain( kvp => kvp.Key.Equals(testFile664Path, StringComparison.OrdinalIgnoreCase) && kvp.Value == GitIndexProjection.FileMode664); mockVirtualization.CreatedPlaceholders.ShouldContain( kvp => kvp.Key.Equals(testFile755Path, StringComparison.OrdinalIgnoreCase) && kvp.Value == GitIndexProjection.FileMode755); fileSystemCallbacks.Stop(); } mockPlaceholderDb.VerifyAll(); mockSparseDb.VerifyAll(); }
public void TestFileSystemOperationsInvalidateStatusCache() { using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockFileSystemVirtualizer fileSystemVirtualizer = new MockFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects)) using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { "test.txt" })) using (MockGitStatusCache gitStatusCache = new MockGitStatusCache(this.Repo.Context, TimeSpan.Zero)) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: gitIndexProjection, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: fileSystemVirtualizer, gitStatusCache: gitStatusCache)) { this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileConvertedToFull, "OnFileConvertedToFull.txt", FileSystemTask.OperationType.OnFileConvertedToFull); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileCreated, "OnFileCreated.txt", FileSystemTask.OperationType.OnFileCreated); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileDeleted, "OnFileDeleted.txt", FileSystemTask.OperationType.OnFileDeleted); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileOverwritten, "OnFileDeleted.txt", FileSystemTask.OperationType.OnFileOverwritten); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileSuperseded, "OnFileSuperseded.txt", FileSystemTask.OperationType.OnFileSuperseded); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFolderCreated, "OnFileSuperseded.txt", FileSystemTask.OperationType.OnFolderCreated); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFolderDeleted, "OnFileSuperseded.txt", FileSystemTask.OperationType.OnFolderDeleted); this.ValidateActionInvalidatesStatusCache(backgroundTaskRunner, gitStatusCache, fileSystemCallbacks.OnFileConvertedToFull, "OnFileConvertedToFull.txt", FileSystemTask.OperationType.OnFileConvertedToFull); } }
private void MountAndStartWorkingDirectoryCallbacks(CacheServerInfo cache) { string error; if (!this.context.Enlistment.Authentication.TryInitialize(this.context.Tracer, this.context.Enlistment, out error)) { this.FailMountAndExit("Failed to obtain git credentials: " + error); } GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(this.context.Tracer, this.context.Enlistment, cache, this.retryConfig); this.gitObjects = new GVFSGitObjects(this.context, objectRequestor); FileSystemVirtualizer virtualizer = this.CreateOrReportAndExit(() => GVFSPlatformLoader.CreateFileSystemVirtualizer(this.context, this.gitObjects), "Failed to create src folder virtualizer"); GitStatusCache gitStatusCache = (!this.context.Unattended && GVFSPlatform.Instance.IsGitStatusCacheSupported()) ? new GitStatusCache(this.context, this.gitStatusCacheConfig) : null; if (gitStatusCache != null) { this.tracer.RelatedInfo("Git status cache enabled. Backoff time: {0}ms", this.gitStatusCacheConfig.BackoffTime.TotalMilliseconds); } else { this.tracer.RelatedInfo("Git status cache is not enabled"); } this.fileSystemCallbacks = this.CreateOrReportAndExit(() => new FileSystemCallbacks(this.context, this.gitObjects, RepoMetadata.Instance, virtualizer, gitStatusCache), "Failed to create src folder callback listener"); this.maintenanceScheduler = this.CreateOrReportAndExit(() => new GitMaintenanceScheduler(this.context, this.gitObjects), "Failed to start maintenance scheduler"); int majorVersion; int minorVersion; if (!RepoMetadata.Instance.TryGetOnDiskLayoutVersion(out majorVersion, out minorVersion, out error)) { this.FailMountAndExit("Error: {0}", error); } if (majorVersion != GVFSPlatform.Instance.DiskLayoutUpgrade.Version.CurrentMajorVersion) { this.FailMountAndExit( "Error: On disk version ({0}) does not match current version ({1})", majorVersion, GVFSPlatform.Instance.DiskLayoutUpgrade.Version.CurrentMajorVersion); } try { if (!this.fileSystemCallbacks.TryStart(out error)) { this.FailMountAndExit("Error: {0}. \r\nPlease confirm that gvfs clone completed without error.", error); } } catch (Exception e) { this.FailMountAndExit("Failed to initialize src folder callbacks. {0}", e.ToString()); } this.heartbeat = new HeartbeatThread(this.tracer, this.fileSystemCallbacks); this.heartbeat.Start(); }
public void UpdatePlaceholderToSymLink() { const string PlaceholderToLinkFileName = "testUpdatePlaceholderToLink.txt"; Mock <IPlaceholderCollection> mockPlaceholderDb = new Mock <IPlaceholderCollection>(MockBehavior.Strict); mockPlaceholderDb.Setup(x => x.GetCount()).Returns(1); using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockVirtualizationInstance mockVirtualization = new MockVirtualizationInstance()) using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { PlaceholderToLinkFileName })) using (MacFileSystemVirtualizer virtualizer = new MacFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects, mockVirtualization)) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection, backgroundTaskRunner, virtualizer, mockPlaceholderDb.Object)) { gitIndexProjection.MockFileTypesAndModes.TryAdd( PlaceholderToLinkFileName, ConvertFileTypeAndModeToIndexFormat(GitIndexProjection.FileType.SymLink, fileMode: 0)); string error; fileSystemCallbacks.TryStart(out error).ShouldEqual(true); UpdateFailureReason failureReason = UpdateFailureReason.NoFailure; mockVirtualization.UpdatePlaceholderIfNeededResult = Result.Success; mockVirtualization.UpdatePlaceholderIfNeededFailureCause = UpdateFailureCause.NoFailure; virtualizer .UpdatePlaceholderIfNeeded( PlaceholderToLinkFileName, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, 0, 15, string.Empty, UpdatePlaceholderType.AllowReadOnly, out failureReason) .ShouldEqual(new FileSystemResult(FSResult.Ok, (int)mockVirtualization.UpdatePlaceholderIfNeededResult)); failureReason.ShouldEqual((UpdateFailureReason)mockVirtualization.UpdatePlaceholderIfNeededFailureCause); mockVirtualization.UpdatedPlaceholders.Count.ShouldEqual(0, "UpdatePlaceholderIfNeeded should not be called when converting a placeholder to a link"); mockVirtualization.CreatedSymLinks.Count.ShouldEqual(1); mockVirtualization.CreatedSymLinks.ShouldContain(entry => entry.Equals(PlaceholderToLinkFileName)); // Creating a symlink should schedule a background task backgroundTaskRunner.Count.ShouldEqual(1); backgroundTaskRunner.BackgroundTasks[0].Operation.ShouldEqual(GVFS.Virtualization.Background.FileSystemTask.OperationType.OnFileSymLinkCreated); backgroundTaskRunner.BackgroundTasks[0].VirtualPath.ShouldEqual(PlaceholderToLinkFileName); fileSystemCallbacks.Stop(); } mockPlaceholderDb.VerifyAll(); }
public void IsPathInsideDotGitIsTrueForDotGitPath() { FileSystemCallbacks.IsPathInsideDotGit(@".git" + Path.DirectorySeparatorChar).ShouldEqual(true); FileSystemCallbacks.IsPathInsideDotGit(@".GIT" + Path.DirectorySeparatorChar).ShouldEqual(true); FileSystemCallbacks.IsPathInsideDotGit(Path.Combine(".git", "test_file.txt")).ShouldEqual(true); FileSystemCallbacks.IsPathInsideDotGit(Path.Combine(".GIT", "test_file.txt")).ShouldEqual(true); FileSystemCallbacks.IsPathInsideDotGit(Path.Combine(".git", "test_folder", "test_file.txt")).ShouldEqual(true); FileSystemCallbacks.IsPathInsideDotGit(Path.Combine(".GIT", "test_folder", "test_file.txt")).ShouldEqual(true); }
public void GetMetadataForHeartBeatDoesSetsEventLevelWToInformationalWhenPlaceholdersHaveBeenCreated() { Mock <IPlaceholderCollection> mockPlaceholderDb = new Mock <IPlaceholderCollection>(MockBehavior.Strict); int placeholderCount = 0; mockPlaceholderDb.Setup(x => x.GetCount()).Returns(() => placeholderCount); mockPlaceholderDb.Setup(x => x.AddFile("test.txt", "1111122222333334444455555666667777788888")).Callback(() => ++ placeholderCount); mockPlaceholderDb.Setup(x => x.AddFile("test.txt", "2222233333444445555566666777778888899999")).Callback(() => ++ placeholderCount); mockPlaceholderDb.Setup(x => x.AddFile("test.txt", "3333344444555556666677777888889999900000")).Callback(() => ++ placeholderCount); using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: null, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: null, placeholderDatabase: mockPlaceholderDb.Object)) { fileSystemCallbacks.OnPlaceholderFileCreated("test.txt", "1111122222333334444455555666667777788888", "GVFS.UnitTests.exe"); EventLevel eventLevel = EventLevel.Verbose; EventMetadata metadata = fileSystemCallbacks.GetMetadataForHeartBeat(ref eventLevel); eventLevel.ShouldEqual(EventLevel.Informational); // "ModifiedPathsCount" should be 1 because ".gitattributes" is always present metadata.Count.ShouldEqual(6); metadata.ShouldContain("ProcessName1", "GVFS.UnitTests.exe"); metadata.ShouldContain("ProcessCount1", 1); metadata.ShouldContain("ModifiedPathsCount", 1); metadata.ShouldContain("PlaceholderCount", 1); metadata.ShouldContain(nameof(RepoMetadata.Instance.EnlistmentId), RepoMetadata.Instance.EnlistmentId); metadata.ContainsKey("PhysicalDiskInfo").ShouldBeTrue(); // Create more placeholders fileSystemCallbacks.OnPlaceholderFileCreated("test.txt", "2222233333444445555566666777778888899999", "GVFS.UnitTests.exe2"); fileSystemCallbacks.OnPlaceholderFileCreated("test.txt", "3333344444555556666677777888889999900000", "GVFS.UnitTests.exe2"); eventLevel = EventLevel.Verbose; metadata = fileSystemCallbacks.GetMetadataForHeartBeat(ref eventLevel); eventLevel.ShouldEqual(EventLevel.Informational); metadata.Count.ShouldEqual(6); // Only processes that have created placeholders since the last heartbeat should be named metadata.ShouldContain("ProcessName1", "GVFS.UnitTests.exe2"); metadata.ShouldContain("ProcessCount1", 2); metadata.ShouldContain("ModifiedPathsCount", 1); metadata.ShouldContain("PlaceholderCount", 3); metadata.ShouldContain(nameof(RepoMetadata.Instance.EnlistmentId), RepoMetadata.Instance.EnlistmentId); metadata.ContainsKey("PhysicalDiskInfo").ShouldBeTrue(); } mockPlaceholderDb.VerifyAll(); }
public void IsPathInsideDotGitIsFalseForNonDotGitPath() { FileSystemCallbacks.IsPathInsideDotGit(@".git").ShouldEqual(false); FileSystemCallbacks.IsPathInsideDotGit(@".GIT").ShouldEqual(false); FileSystemCallbacks.IsPathInsideDotGit(@".gitattributes").ShouldEqual(false); FileSystemCallbacks.IsPathInsideDotGit(@".gitignore").ShouldEqual(false); FileSystemCallbacks.IsPathInsideDotGit(@".gitsubfolder\").ShouldEqual(false); FileSystemCallbacks.IsPathInsideDotGit(@".gitsubfolder\test_file.txt").ShouldEqual(false); FileSystemCallbacks.IsPathInsideDotGit(@"test_file.txt").ShouldEqual(false); FileSystemCallbacks.IsPathInsideDotGit(@"test_folder\test_file.txt").ShouldEqual(false); }
public void Initialize(FileSystemCallbacks fileSystemCallbacks) { this.FileSystemCallbacks = fileSystemCallbacks; this.fileAndNetworkWorkerThreads = new Thread[this.numWorkerThreads]; for (int i = 0; i < this.fileAndNetworkWorkerThreads.Length; ++i) { this.fileAndNetworkWorkerThreads[i] = new Thread(this.ExecuteFileOrNetworkRequest); this.fileAndNetworkWorkerThreads[i].IsBackground = true; this.fileAndNetworkWorkerThreads[i].Start(); } }
private void MountAndStartWorkingDirectoryCallbacks(CacheServerInfo cache) { string error; if (!this.context.Enlistment.Authentication.TryRefreshCredentials(this.context.Tracer, out error)) { this.FailMountAndExit("Failed to obtain git credentials: " + error); } GitObjectsHttpRequestor objectRequestor = new GitObjectsHttpRequestor(this.context.Tracer, this.context.Enlistment, cache, this.retryConfig); this.gitObjects = new GVFSGitObjects(this.context, objectRequestor); FileSystemVirtualizer virtualizer = this.CreateOrReportAndExit(() => GVFSPlatformLoader.CreateFileSystemVirtualizer(this.context, this.gitObjects), "Failed to create src folder virtualizer"); this.fileSystemCallbacks = this.CreateOrReportAndExit(() => new FileSystemCallbacks(this.context, this.gitObjects, RepoMetadata.Instance, virtualizer), "Failed to create src folder callback listener"); if (!this.context.Unattended) { this.prefetcher = this.CreateOrReportAndExit(() => new BackgroundPrefetcher(this.tracer, this.enlistment, this.context.FileSystem, this.gitObjects), "Failed to start background prefetcher"); } int majorVersion; int minorVersion; if (!RepoMetadata.Instance.TryGetOnDiskLayoutVersion(out majorVersion, out minorVersion, out error)) { this.FailMountAndExit("Error: {0}", error); } if (majorVersion != RepoMetadata.DiskLayoutVersion.CurrentMajorVersion) { this.FailMountAndExit( "Error: On disk version ({0}) does not match current version ({1})", majorVersion, RepoMetadata.DiskLayoutVersion.CurrentMajorVersion); } try { if (!this.fileSystemCallbacks.TryStart(out error)) { this.FailMountAndExit("Error: {0}. \r\nPlease confirm that gvfs clone completed without error.", error); } } catch (Exception e) { this.FailMountAndExit("Failed to initialize src folder callbacks. {0}", e.ToString()); } this.heartbeat = new HeartbeatThread(this.tracer, this.fileSystemCallbacks); this.heartbeat.Start(); }
public void OnGetFileStreamReturnsSuccessWhenFileStreamAvailable() { const string TestFileName = "test.txt"; Mock <IPlaceholderCollection> mockPlaceholderDb = new Mock <IPlaceholderCollection>(MockBehavior.Strict); mockPlaceholderDb.Setup(x => x.GetCount()).Returns(1); Mock <ISparseCollection> mockSparseDb = new Mock <ISparseCollection>(MockBehavior.Strict); using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockVirtualizationInstance mockVirtualization = new MockVirtualizationInstance()) using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { TestFileName })) using (MacFileSystemVirtualizer virtualizer = new MacFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects, mockVirtualization)) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection, backgroundTaskRunner, virtualizer, mockPlaceholderDb.Object, mockSparseDb.Object)) { string error; fileSystemCallbacks.TryStart(out error).ShouldEqual(true); byte[] contentId = FileSystemVirtualizer.ConvertShaToContentId("0123456789012345678901234567890123456789"); byte[] placeholderVersion = MacFileSystemVirtualizer.PlaceholderVersionId; uint fileLength = 100; MockGVFSGitObjects mockGVFSGitObjects = this.Repo.GitObjects as MockGVFSGitObjects; mockGVFSGitObjects.FileLength = fileLength; mockVirtualization.WriteFileReturnResult = Result.Success; mockVirtualization.OnGetFileStream( commandId: 1, relativePath: TestFileName, providerId: placeholderVersion, contentId: contentId, triggeringProcessId: 2, triggeringProcessName: "UnitTest", fileHandle: IntPtr.Zero).ShouldEqual(Result.Success); mockVirtualization.BytesWritten.ShouldEqual(fileLength); fileSystemCallbacks.Stop(); } mockPlaceholderDb.VerifyAll(); mockSparseDb.VerifyAll(); }
public void WritePlaceholderForSymLink() { const string WriteSymLinkFileName = "testWriteSymLink.txt"; Mock <IPlaceholderCollection> mockPlaceholderDb = new Mock <IPlaceholderCollection>(MockBehavior.Strict); mockPlaceholderDb.Setup(x => x.GetCount()).Returns(1); Mock <ISparseCollection> mockSparseDb = new Mock <ISparseCollection>(MockBehavior.Strict); using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockVirtualizationInstance mockVirtualization = new MockVirtualizationInstance()) using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { WriteSymLinkFileName })) using (MacFileSystemVirtualizer virtualizer = new MacFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects, mockVirtualization)) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection, backgroundTaskRunner, virtualizer, mockPlaceholderDb.Object, mockSparseDb.Object)) { gitIndexProjection.MockFileTypesAndModes.TryAdd( WriteSymLinkFileName, ConvertFileTypeAndModeToIndexFormat(GitIndexProjection.FileType.SymLink, fileMode: 0)); string error; fileSystemCallbacks.TryStart(out error).ShouldEqual(true); virtualizer.WritePlaceholderFile( WriteSymLinkFileName, endOfFile: 0, sha: string.Empty).ShouldEqual(new FileSystemResult(FSResult.Ok, (int)Result.Success)); mockVirtualization.CreatedPlaceholders.ShouldBeEmpty(); mockVirtualization.CreatedSymLinks.Count.ShouldEqual(1); mockVirtualization.CreatedSymLinks.ShouldContain(entry => entry.Equals(WriteSymLinkFileName)); // Creating a symlink should schedule a background task backgroundTaskRunner.Count.ShouldEqual(1); backgroundTaskRunner.BackgroundTasks[0].Operation.ShouldEqual(GVFS.Virtualization.Background.FileSystemTask.OperationType.OnFileSymLinkCreated); backgroundTaskRunner.BackgroundTasks[0].VirtualPath.ShouldEqual(WriteSymLinkFileName); fileSystemCallbacks.Stop(); } mockPlaceholderDb.VerifyAll(); mockSparseDb.VerifyAll(); }
public virtual bool TryStart(FileSystemCallbacks fileSystemCallbacks, out string error) { this.FileSystemCallbacks = fileSystemCallbacks; this.fileAndNetworkWorkerThreads = new Thread[this.numWorkerThreads]; for (int i = 0; i < this.fileAndNetworkWorkerThreads.Length; ++i) { this.fileAndNetworkWorkerThreads[i] = new Thread(this.ExecuteFileOrNetworkRequest); this.fileAndNetworkWorkerThreads[i].IsBackground = true; this.fileAndNetworkWorkerThreads[i].Start(); } return(this.TryStart(out error)); }
private void UnmountAndStopWorkingDirectoryCallbacks() { if (this.heartbeat != null) { this.heartbeat.Stop(); this.heartbeat = null; } if (this.fileSystemCallbacks != null) { this.fileSystemCallbacks.Stop(); this.fileSystemCallbacks.Dispose(); this.fileSystemCallbacks = null; } }
public void GetMetadataForHeartBeatDoesSetsEventLevelWToInformationalWhenPlaceholdersHaveBeenCreated() { using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: null, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: null)) { fileSystemCallbacks.OnPlaceholderFileCreated("test.txt", "1111122222333334444455555666667777788888", "GVFS.UnitTests.exe"); EventLevel eventLevel = EventLevel.Verbose; EventMetadata metadata = fileSystemCallbacks.GetMetadataForHeartBeat(ref eventLevel); eventLevel.ShouldEqual(EventLevel.Informational); // "ModifiedPathsCount" should be 1 because ".gitattributes" is always present metadata.Count.ShouldEqual(5); metadata.ShouldContain("ProcessName1", "GVFS.UnitTests.exe"); metadata.ShouldContain("ProcessCount1", 1); metadata.ShouldContain("ModifiedPathsCount", 1); metadata.ShouldContain("PlaceholderCount", 1); metadata.ShouldContain(nameof(RepoMetadata.Instance.EnlistmentId), RepoMetadata.Instance.EnlistmentId); // Create more placeholders fileSystemCallbacks.OnPlaceholderFileCreated("test.txt", "2222233333444445555566666777778888899999", "GVFS.UnitTests.exe2"); fileSystemCallbacks.OnPlaceholderFileCreated("test.txt", "3333344444555556666677777888889999900000", "GVFS.UnitTests.exe2"); eventLevel = EventLevel.Verbose; metadata = fileSystemCallbacks.GetMetadataForHeartBeat(ref eventLevel); eventLevel.ShouldEqual(EventLevel.Informational); metadata.Count.ShouldEqual(5); // Only processes that have created placeholders since the last heartbeat should be named metadata.ShouldContain("ProcessName1", "GVFS.UnitTests.exe2"); metadata.ShouldContain("ProcessCount1", 2); metadata.ShouldContain("ModifiedPathsCount", 1); metadata.ShouldContain("PlaceholderCount", 3); metadata.ShouldContain(nameof(RepoMetadata.Instance.EnlistmentId), RepoMetadata.Instance.EnlistmentId); } }
private void FailMountAndExit(string error, params object[] args) { this.currentState = MountState.MountFailed; this.tracer.RelatedError(error, args); if (this.showDebugWindow) { Console.WriteLine("\nPress Enter to Exit"); Console.ReadLine(); } if (this.fileSystemCallbacks != null) { this.fileSystemCallbacks.Dispose(); this.fileSystemCallbacks = null; } Environment.Exit((int)ReturnCode.GenericError); }
public void BackgroundOperationCountMatchesBackgroundFileSystemTaskRunner() { using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: null, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: null)) { fileSystemCallbacks.BackgroundOperationCount.ShouldEqual(backgroundTaskRunner.Count); fileSystemCallbacks.OnFileConvertedToFull("Path1.txt"); fileSystemCallbacks.OnFileConvertedToFull("Path2.txt"); backgroundTaskRunner.Count.ShouldEqual(2); fileSystemCallbacks.BackgroundOperationCount.ShouldEqual(backgroundTaskRunner.Count); } }
public void OnGetFileStreamReturnsErrorWhenWriteFileContentsFails() { const string TestFileName = "test.txt"; using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockVirtualizationInstance mockVirtualization = new MockVirtualizationInstance()) using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { TestFileName })) using (MacFileSystemVirtualizer virtualizer = new MacFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects, mockVirtualization)) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: virtualizer)) { string error; fileSystemCallbacks.TryStart(out error).ShouldEqual(true); byte[] contentId = FileSystemVirtualizer.ConvertShaToContentId("0123456789012345678901234567890123456789"); byte[] placeholderVersion = MacFileSystemVirtualizer.PlaceholderVersionId; uint fileLength = 100; MockGVFSGitObjects mockGVFSGitObjects = this.Repo.GitObjects as MockGVFSGitObjects; mockGVFSGitObjects.FileLength = fileLength; mockVirtualization.WriteFileReturnResult = Result.EIOError; mockVirtualization.OnGetFileStream( commandId: 1, relativePath: TestFileName, providerId: placeholderVersion, contentId: contentId, triggeringProcessId: 2, triggeringProcessName: "UnitTest", fileHandle: IntPtr.Zero).ShouldEqual(Result.EIOError); fileSystemCallbacks.Stop(); } }
public void GetMetadataForHeartBeatDoesNotChangeEventLevelWhenNoPlaceholderHaveBeenCreated() { using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: null, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: null)) { EventLevel eventLevel = EventLevel.Verbose; EventMetadata metadata = fileSystemCallbacks.GetMetadataForHeartBeat(ref eventLevel); eventLevel.ShouldEqual(EventLevel.Verbose); // "ModifiedPathsCount" should be 1 because ".gitattributes" is always present metadata.ShouldContain("ModifiedPathsCount", 1); metadata.ShouldContain("PlaceholderCount", 0); metadata.ShouldContain(nameof(RepoMetadata.Instance.EnlistmentId), RepoMetadata.Instance.EnlistmentId); } }
public void OnEnumerateDirectoryReturnsSuccessWhenResultsInMemory() { const string TestFileName = "test.txt"; const string TestFolderName = "testFolder"; string testFilePath = Path.Combine(TestFolderName, TestFileName); using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockVirtualizationInstance mockVirtualization = new MockVirtualizationInstance()) // Don't include TestFolderName as MockGitIndexProjection returns the same list of files regardless of what folder name // it is passed using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { TestFileName })) using (MacFileSystemVirtualizer virtualizer = new MacFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects, mockVirtualization)) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: virtualizer)) { gitIndexProjection.MockFileTypesAndModes.TryAdd( testFilePath, ConvertFileTypeAndModeToIndexFormat(GitIndexProjection.FileType.Regular, GitIndexProjection.FileMode644)); string error; fileSystemCallbacks.TryStart(out error).ShouldEqual(true); Guid enumerationGuid = Guid.NewGuid(); gitIndexProjection.EnumerationInMemory = true; mockVirtualization.OnEnumerateDirectory(1, TestFolderName, triggeringProcessId: 1, triggeringProcessName: "UnitTests").ShouldEqual(Result.Success); mockVirtualization.CreatedPlaceholders.ShouldContain( kvp => kvp.Key.Equals(testFilePath, StringComparison.OrdinalIgnoreCase) && kvp.Value == GitIndexProjection.FileMode644); gitIndexProjection.ExpandedFolders.ShouldMatchInOrder(TestFolderName); fileSystemCallbacks.Stop(); } }
public void StartingAndStoppingSetsMountedState() { using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockFileSystemVirtualizer fileSystemVirtualizer = new MockFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects)) using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { "test.txt" })) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: gitIndexProjection, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: fileSystemVirtualizer)) { fileSystemCallbacks.IsMounted.ShouldBeFalse(); string error; fileSystemCallbacks.TryStart(out error).ShouldBeTrue(); fileSystemCallbacks.IsMounted.ShouldBeTrue(); fileSystemCallbacks.Stop(); fileSystemCallbacks.IsMounted.ShouldBeFalse(); } }
private void UnmountAndStopWorkingDirectoryCallbacks() { if (this.maintenanceScheduler != null) { this.maintenanceScheduler.Dispose(); this.maintenanceScheduler = null; } if (this.heartbeat != null) { this.heartbeat.Stop(); this.heartbeat = null; } if (this.fileSystemCallbacks != null) { this.fileSystemCallbacks.Stop(); this.fileSystemCallbacks.Dispose(); this.fileSystemCallbacks = null; } this.gvfsDatabase?.Dispose(); this.gvfsDatabase = null; }
public void FileAndFolderCallbacksScheduleBackgroundTasks() { using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: null, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: null)) { this.CallbackSchedulesBackgroundTask( backgroundTaskRunner, (path) => fileSystemCallbacks.OnFileConvertedToFull(path), "OnFileConvertedToFull.txt", FileSystemTask.OperationType.OnFileConvertedToFull); this.CallbackSchedulesBackgroundTask( backgroundTaskRunner, (path) => fileSystemCallbacks.OnFileCreated(path), "OnFileCreated.txt", FileSystemTask.OperationType.OnFileCreated); this.CallbackSchedulesBackgroundTask( backgroundTaskRunner, (path) => fileSystemCallbacks.OnFileDeleted(path), "OnFileDeleted.txt", FileSystemTask.OperationType.OnFileDeleted); this.CallbackSchedulesBackgroundTask( backgroundTaskRunner, (path) => fileSystemCallbacks.OnFileOverwritten(path), "OnFileOverwritten.txt", FileSystemTask.OperationType.OnFileOverwritten); this.CallbackSchedulesBackgroundTask( backgroundTaskRunner, (oldPath, newPath) => fileSystemCallbacks.OnFileRenamed(oldPath, newPath), "OnFileRenamed.txt", "OnFileRenamed2.txt", FileSystemTask.OperationType.OnFileRenamed); this.CallbackSchedulesBackgroundTask( backgroundTaskRunner, (path) => fileSystemCallbacks.OnFileSuperseded(path), "OnFileSuperseded.txt", FileSystemTask.OperationType.OnFileSuperseded); this.CallbackSchedulesBackgroundTask( backgroundTaskRunner, (path) => fileSystemCallbacks.OnFolderCreated(path), "OnFolderCreated.txt", FileSystemTask.OperationType.OnFolderCreated); this.CallbackSchedulesBackgroundTask( backgroundTaskRunner, (path) => fileSystemCallbacks.OnFolderDeleted(path), "OnFolderDeleted.txt", FileSystemTask.OperationType.OnFolderDeleted); this.CallbackSchedulesBackgroundTask( backgroundTaskRunner, (oldPath, newPath) => fileSystemCallbacks.OnFolderRenamed(oldPath, newPath), "OnFolderRenamed.txt", "OnFolderRenamed2.txt", FileSystemTask.OperationType.OnFolderRenamed); } }
public void EmptyStringIsNotInsideDotGitPath() { FileSystemCallbacks.IsPathInsideDotGit(string.Empty).ShouldEqual(false); }
public void IsReadyForExternalAcquireLockRequests() { using (MockBackgroundFileSystemTaskRunner backgroundTaskRunner = new MockBackgroundFileSystemTaskRunner()) using (MockFileSystemVirtualizer fileSystemVirtualizer = new MockFileSystemVirtualizer(this.Repo.Context, this.Repo.GitObjects)) using (MockGitIndexProjection gitIndexProjection = new MockGitIndexProjection(new[] { "test.txt" })) using (FileSystemCallbacks fileSystemCallbacks = new FileSystemCallbacks( this.Repo.Context, this.Repo.GitObjects, RepoMetadata.Instance, new MockBlobSizes(), gitIndexProjection: gitIndexProjection, backgroundFileSystemTaskRunner: backgroundTaskRunner, fileSystemVirtualizer: fileSystemVirtualizer)) { string denyMessage; fileSystemCallbacks.IsReadyForExternalAcquireLockRequests( new NamedPipeMessages.LockData( pid: 0, isElevated: false, checkAvailabilityOnly: false, parsedCommand: "git dummy-command"), out denyMessage).ShouldBeFalse(); denyMessage.ShouldEqual("Waiting for mount to complete"); string error; fileSystemCallbacks.TryStart(out error).ShouldBeTrue(); gitIndexProjection.ProjectionParseComplete = false; fileSystemCallbacks.IsReadyForExternalAcquireLockRequests( new NamedPipeMessages.LockData( pid: 0, isElevated: false, checkAvailabilityOnly: false, parsedCommand: "git dummy-command"), out denyMessage).ShouldBeFalse(); denyMessage.ShouldEqual("Waiting for GVFS to parse index and update placeholder files"); // Put something on the background queue fileSystemCallbacks.OnFileCreated("NewFilePath.txt"); backgroundTaskRunner.Count.ShouldEqual(1); fileSystemCallbacks.IsReadyForExternalAcquireLockRequests( new NamedPipeMessages.LockData( pid: 0, isElevated: false, checkAvailabilityOnly: false, parsedCommand: "git dummy-command"), out denyMessage).ShouldBeFalse(); denyMessage.ShouldEqual("Waiting for background operations to complete and for GVFS to release the lock"); backgroundTaskRunner.BackgroundTasks.Clear(); gitIndexProjection.ProjectionParseComplete = true; fileSystemCallbacks.IsReadyForExternalAcquireLockRequests( new NamedPipeMessages.LockData( pid: 0, isElevated: false, checkAvailabilityOnly: false, parsedCommand: "git dummy-command"), out denyMessage).ShouldBeTrue(); denyMessage.ShouldEqual("Waiting for GVFS to release the lock"); fileSystemCallbacks.Stop(); } }