private void AlternatesFileShouldHaveGitObjectsRoot(GSDFunctionalTestEnlistment enlistment) { string objectsRoot = GSDHelpers.GetPersistedGitObjectsRoot(enlistment.DotGSDRoot); string alternatesFileContents = Path.Combine(enlistment.RepoRoot, ".git", "objects", "info", "alternates").ShouldBeAFile(this.fileSystem).WithContents(); alternatesFileContents.ShouldEqual(objectsRoot); }
public void CloneWithDefaultLocalCacheLocation() { FileSystemRunner fileSystem = FileSystemRunner.DefaultRunner; string homeDirectory = Environment.GetEnvironmentVariable("HOME"); homeDirectory.ShouldBeADirectory(fileSystem); string newEnlistmentRoot = GSDFunctionalTestEnlistment.GetUniqueEnlistmentRoot(); ProcessStartInfo processInfo = new ProcessStartInfo(GSDTestConfig.PathToGSD); processInfo.Arguments = $"clone {Properties.Settings.Default.RepoToClone} {newEnlistmentRoot} --no-mount --no-prefetch"; processInfo.WindowStyle = ProcessWindowStyle.Hidden; processInfo.CreateNoWindow = true; processInfo.UseShellExecute = false; processInfo.RedirectStandardOutput = true; ProcessResult result = ProcessHelper.Run(processInfo); result.ExitCode.ShouldEqual(0, result.Errors); string dotGSDRoot = Path.Combine(newEnlistmentRoot, GSDTestConfig.DotGSDRoot); dotGSDRoot.ShouldBeADirectory(fileSystem); string localCacheRoot = GSDHelpers.GetPersistedLocalCacheRoot(dotGSDRoot); string gitObjectsRoot = GSDHelpers.GetPersistedGitObjectsRoot(dotGSDRoot); string defaultGSDCacheRoot = Path.Combine(homeDirectory, ".gvfsCache"); localCacheRoot.StartsWith(defaultGSDCacheRoot, StringComparison.Ordinal).ShouldBeTrue($"Local cache root did not default to using {homeDirectory}"); gitObjectsRoot.StartsWith(defaultGSDCacheRoot, StringComparison.Ordinal).ShouldBeTrue($"Git objects root did not default to using {homeDirectory}"); RepositoryHelpers.DeleteTestDirectory(newEnlistmentRoot); }
public void ServiceCommandsWithMountAndUnmount() { GSDFunctionalTestEnlistment enlistment1 = this.CreateNewEnlistment(); string[] repoRootList = new string[] { enlistment1.EnlistmentRoot }; GSDProcess gvfsProcess1 = new GSDProcess( GSDTestConfig.PathToGSD, enlistment1.EnlistmentRoot, enlistment1.LocalCacheRoot); this.RunServiceCommandAndCheckOutput("--list-mounted", expectedRepoRoots: repoRootList); gvfsProcess1.Unmount(); this.RunServiceCommandAndCheckOutput("--list-mounted", EmptyRepoList, unexpectedRepoRoots: repoRootList); this.RunServiceCommandAndCheckOutput("--unmount-all", EmptyRepoList, unexpectedRepoRoots: repoRootList); this.RunServiceCommandAndCheckOutput("--mount-all", EmptyRepoList, unexpectedRepoRoots: repoRootList); // Check that it is still unmounted gvfsProcess1.IsEnlistmentMounted().ShouldEqual(false); gvfsProcess1.Mount(); this.RunServiceCommandAndCheckOutput("--unmount-all", expectedRepoRoots: repoRootList); this.RunServiceCommandAndCheckOutput("--mount-all", expectedRepoRoots: repoRootList); }
public void DeleteCacheDuringHydrations() { GSDFunctionalTestEnlistment enlistment1 = this.CloneAndMountEnlistment(); string objectsRoot = GSDHelpers.GetPersistedGitObjectsRoot(enlistment1.DotGSDRoot).ShouldNotBeNull(); objectsRoot.ShouldBeADirectory(this.fileSystem); Task task1 = Task.Run(() => { this.HydrateEntireRepo(enlistment1); }); while (!task1.IsCompleted) { try { // Delete objectsRoot rather than this.localCachePath as the blob sizes database cannot be deleted while GSD is mounted RepositoryHelpers.DeleteTestDirectory(objectsRoot); Thread.Sleep(100); } catch (IOException) { // Hydration may have handles into the cache, so failing this delete is expected. } } task1.Exception.ShouldBeNull(); enlistment1.Status().ShouldContain("Mount status: Ready"); }
public void MountReusesLocalCacheKeyWhenGitObjectsRootDeleted() { GSDFunctionalTestEnlistment enlistment = this.CloneAndMountEnlistment(); enlistment.UnmountGSD(); // Find the current git objects root and ensure it's on disk string objectsRoot = GSDHelpers.GetPersistedGitObjectsRoot(enlistment.DotGSDRoot).ShouldNotBeNull(); objectsRoot.ShouldBeADirectory(this.fileSystem); string mappingFilePath = Path.Combine(enlistment.LocalCacheRoot, "mapping.dat"); string mappingFileContents = this.fileSystem.ReadAllText(mappingFilePath); mappingFileContents.Length.ShouldNotEqual(0, "mapping.dat should not be empty"); // Delete the git objects root folder, mount should re-create it and the mapping.dat file should not change RepositoryHelpers.DeleteTestDirectory(objectsRoot); enlistment.MountGSD(); GSDHelpers.GetPersistedGitObjectsRoot(enlistment.DotGSDRoot).ShouldEqual(objectsRoot); objectsRoot.ShouldBeADirectory(this.fileSystem); mappingFilePath.ShouldBeAFile(this.fileSystem).WithContents(mappingFileContents); this.AlternatesFileShouldHaveGitObjectsRoot(enlistment); }
public void DeleteObjectsCacheAndCacheMappingBeforeMount() { GSDFunctionalTestEnlistment enlistment1 = this.CloneAndMountEnlistment(); GSDFunctionalTestEnlistment enlistment2 = this.CloneAndMountEnlistment(); enlistment1.UnmountGSD(); string objectsRoot = GSDHelpers.GetPersistedGitObjectsRoot(enlistment1.DotGSDRoot).ShouldNotBeNull(); objectsRoot.ShouldBeADirectory(this.fileSystem); RepositoryHelpers.DeleteTestDirectory(objectsRoot); string metadataPath = Path.Combine(this.localCachePath, "mapping.dat"); metadataPath.ShouldBeAFile(this.fileSystem); this.fileSystem.DeleteFile(metadataPath); enlistment1.MountGSD(); Task task1 = Task.Run(() => this.HydrateRootFolder(enlistment1)); Task task2 = Task.Run(() => this.HydrateRootFolder(enlistment2)); task1.Wait(); task2.Wait(); task1.Exception.ShouldBeNull(); task2.Exception.ShouldBeNull(); enlistment1.Status().ShouldContain("Mount status: Ready"); enlistment2.Status().ShouldContain("Mount status: Ready"); this.AlternatesFileShouldHaveGitObjectsRoot(enlistment1); this.AlternatesFileShouldHaveGitObjectsRoot(enlistment2); }
public void ParallelReadsInASharedCache() { GSDFunctionalTestEnlistment enlistment1 = this.CloneAndMountEnlistment(); GSDFunctionalTestEnlistment enlistment2 = this.CloneAndMountEnlistment(); GSDFunctionalTestEnlistment enlistment3 = null; Task task1 = Task.Run(() => this.HydrateEntireRepo(enlistment1)); Task task2 = Task.Run(() => this.HydrateEntireRepo(enlistment2)); Task task3 = Task.Run(() => enlistment3 = this.CloneAndMountEnlistment()); task1.Wait(); task2.Wait(); task3.Wait(); task1.Exception.ShouldBeNull(); task2.Exception.ShouldBeNull(); task3.Exception.ShouldBeNull(); enlistment1.Status().ShouldContain("Mount status: Ready"); enlistment2.Status().ShouldContain("Mount status: Ready"); enlistment3.Status().ShouldContain("Mount status: Ready"); this.AlternatesFileShouldHaveGitObjectsRoot(enlistment1); this.AlternatesFileShouldHaveGitObjectsRoot(enlistment2); this.AlternatesFileShouldHaveGitObjectsRoot(enlistment3); }
public static void OutputGSDLogs(GSDFunctionalTestEnlistment enlistment) { if (enlistment == null) { return; } Console.WriteLine("GSD logs output attached below.\n\n"); foreach (string filename in GetAllFilesInDirectory(enlistment.GSDLogsRoot)) { if (filename.Contains("mount_process")) { // Validate that all mount processes started by the functional tests were started // by verbs, and that "StartedByVerb" was set to true when the mount process was launched OutputFileContents( filename, contents => contents.ShouldContain("\"StartedByVerb\":true")); } else { OutputFileContents(filename); } } }
protected void CreateEnlistment(string commitish = null) { this.Enlistment = GSDFunctionalTestEnlistment.CloneAndMount(GSDTestConfig.PathToGSD, commitish: commitish); GitProcess.Invoke(this.Enlistment.RepoRoot, "config advice.statusUoption false"); this.ControlGitRepo = ControlGitRepo.Create(commitish); this.ControlGitRepo.Initialize(); }
public static void EnsureSubfoldersOnDisk(GSDFunctionalTestEnlistment enlistment, FileSystemRunner fileSystem) { // Enumerate the directory to ensure that the folder is on disk after GSD is unmounted foreach (object[] folder in Folders) { string folderPath = enlistment.GetVirtualPathTo((string)folder[0]); folderPath.ShouldBeADirectory(fileSystem).WithItems(); } }
private void HydrateRootFolder(GSDFunctionalTestEnlistment enlistment) { List <string> allFiles = Directory.EnumerateFiles(enlistment.RepoRoot, "*", SearchOption.TopDirectoryOnly).ToList(); for (int i = 0; i < allFiles.Count; ++i) { File.ReadAllText(allFiles[i]); } }
public void DownloadingACommitWithoutTreesDoesntBreakNextClone() { GSDFunctionalTestEnlistment enlistment1 = this.CloneAndMountEnlistment(); GitProcess.Invoke(enlistment1.RepoRoot, "cat-file -s " + WellKnownCommitSha).ShouldEqual("293\n"); GSDFunctionalTestEnlistment enlistment2 = this.CloneAndMountEnlistment(WellKnownBranch); enlistment2.Status().ShouldContain("Mount status: Ready"); }
public virtual void CreateEnlistment() { if (this.forcePerRepoObjectCache) { this.Enlistment = GSDFunctionalTestEnlistment.CloneAndMountWithPerRepoCache(GSDTestConfig.PathToGSD, skipPrefetch: false); } else { this.Enlistment = GSDFunctionalTestEnlistment.CloneAndMount(GSDTestConfig.PathToGSD); } }
private void HydrateEntireRepo(GSDFunctionalTestEnlistment enlistment) { List <string> allFiles = Directory.EnumerateFiles(enlistment.RepoRoot, "*", SearchOption.AllDirectories).ToList(); for (int i = 0; i < allFiles.Count; ++i) { if (!allFiles[i].StartsWith(enlistment.RepoRoot + "\\.git\\", StringComparison.OrdinalIgnoreCase)) { File.ReadAllText(allFiles[i]); } } }
protected GSDFunctionalTestEnlistment CreateNewEnlistment( string localCacheRoot = null, string branch = null, bool skipPrefetch = false) { GSDFunctionalTestEnlistment output = GSDFunctionalTestEnlistment.CloneAndMount( GSDTestConfig.PathToGSD, branch, localCacheRoot, skipPrefetch); this.enlistmentsToDelete.Add(output); return(output); }
public void CloneCleansUpStaleMetadataLock() { GSDFunctionalTestEnlistment enlistment1 = this.CloneAndMountEnlistment(); string metadataLockPath = Path.Combine(this.localCachePath, "mapping.dat.lock"); metadataLockPath.ShouldNotExistOnDisk(this.fileSystem); this.fileSystem.WriteAllText(metadataLockPath, enlistment1.EnlistmentRoot); metadataLockPath.ShouldBeAFile(this.fileSystem); GSDFunctionalTestEnlistment enlistment2 = this.CloneAndMountEnlistment(); metadataLockPath.ShouldNotExistOnDisk(this.fileSystem); enlistment1.Status().ShouldContain("Mount status: Ready"); enlistment2.Status().ShouldContain("Mount status: Ready"); }
public void CloneWithLocalCachePathWithinSrc() { string newEnlistmentRoot = GSDFunctionalTestEnlistment.GetUniqueEnlistmentRoot(); ProcessStartInfo processInfo = new ProcessStartInfo(GSDTestConfig.PathToGSD); processInfo.Arguments = $"clone {Properties.Settings.Default.RepoToClone} {newEnlistmentRoot} --local-cache-path {Path.Combine(newEnlistmentRoot, "src", ".gvfsCache")}"; processInfo.WindowStyle = ProcessWindowStyle.Hidden; processInfo.CreateNoWindow = true; processInfo.WorkingDirectory = Path.GetDirectoryName(this.Enlistment.EnlistmentRoot); processInfo.UseShellExecute = false; processInfo.RedirectStandardOutput = true; ProcessResult result = ProcessHelper.Run(processInfo); result.ExitCode.ShouldEqual(GSDGenericError); result.Output.ShouldContain("'--local-cache-path' cannot be inside the src folder"); }
public void RepairFixesCorruptBlobSizesDatabase() { GSDFunctionalTestEnlistment enlistment = this.CloneAndMountEnlistment(); enlistment.UnmountGSD(); // Repair on a healthy enlistment should succeed enlistment.Repair(confirm: true); string blobSizesRoot = GSDHelpers.GetPersistedBlobSizesRoot(enlistment.DotGSDRoot).ShouldNotBeNull(); string blobSizesDbPath = Path.Combine(blobSizesRoot, "BlobSizes.sql"); blobSizesDbPath.ShouldBeAFile(this.fileSystem); this.fileSystem.WriteAllText(blobSizesDbPath, "0000"); enlistment.TryMountGSD().ShouldEqual(false, "GSD shouldn't mount when blob size db is corrupt"); enlistment.Repair(confirm: true); enlistment.MountGSD(); }
public void SecondCloneSucceedsWithMissingTrees() { string newCachePath = Path.Combine(this.localCacheParentPath, ".customGvfsCache2"); GSDFunctionalTestEnlistment enlistment1 = this.CreateNewEnlistment(localCacheRoot: newCachePath, skipPrefetch: true); File.ReadAllText(Path.Combine(enlistment1.RepoRoot, WellKnownFile)); this.AlternatesFileShouldHaveGitObjectsRoot(enlistment1); // This Git command loads the commit and root tree for WellKnownCommitSha, // but does not download any more reachable objects. string command = "cat-file -p origin/" + WellKnownBranch + "^{tree}"; ProcessResult result = GitHelpers.InvokeGitAgainstGSDRepo(enlistment1.RepoRoot, command); result.ExitCode.ShouldEqual(0, $"git {command} failed with error: " + result.Errors); // If we did not properly check the failed checkout at this step, then clone will fail during checkout. GSDFunctionalTestEnlistment enlistment2 = this.CreateNewEnlistment(localCacheRoot: newCachePath, branch: WellKnownBranch, skipPrefetch: true); File.ReadAllText(Path.Combine(enlistment2.RepoRoot, WellKnownFile)); }
public void SecondCloneDoesNotDownloadAdditionalObjects() { GSDFunctionalTestEnlistment enlistment1 = this.CloneAndMountEnlistment(); File.ReadAllText(Path.Combine(enlistment1.RepoRoot, WellKnownFile)); this.AlternatesFileShouldHaveGitObjectsRoot(enlistment1); string[] allObjects = Directory.EnumerateFiles(enlistment1.LocalCacheRoot, "*", SearchOption.AllDirectories).ToArray(); GSDFunctionalTestEnlistment enlistment2 = this.CloneAndMountEnlistment(); File.ReadAllText(Path.Combine(enlistment2.RepoRoot, WellKnownFile)); this.AlternatesFileShouldHaveGitObjectsRoot(enlistment2); enlistment2.LocalCacheRoot.ShouldEqual(enlistment1.LocalCacheRoot, "Sanity: Local cache roots are expected to match."); Directory.EnumerateFiles(enlistment2.LocalCacheRoot, "*", SearchOption.AllDirectories) .ShouldMatchInOrder(allObjects); }
public void MountUsesNewLocalCacheKeyWhenLocalCacheDeleted() { GSDFunctionalTestEnlistment enlistment = this.CloneAndMountEnlistment(); enlistment.UnmountGSD(); // Find the current git objects root and ensure it's on disk string objectsRoot = GSDHelpers.GetPersistedGitObjectsRoot(enlistment.DotGSDRoot).ShouldNotBeNull(); objectsRoot.ShouldBeADirectory(this.fileSystem); string mappingFilePath = Path.Combine(enlistment.LocalCacheRoot, "mapping.dat"); string mappingFileContents = this.fileSystem.ReadAllText(mappingFilePath); mappingFileContents.Length.ShouldNotEqual(0, "mapping.dat should not be empty"); // Delete the local cache folder, mount should re-create it and generate a new mapping file and local cache key RepositoryHelpers.DeleteTestDirectory(enlistment.LocalCacheRoot); enlistment.MountGSD(); // Mount should recreate the local cache root enlistment.LocalCacheRoot.ShouldBeADirectory(this.fileSystem); // Determine the new local cache key string newMappingFileContents = mappingFilePath.ShouldBeAFile(this.fileSystem).WithContents(); const int GuidStringLength = 32; string mappingFileKey = "A {\"Key\":\"https://gvfs.visualstudio.com/ci/_git/fortests\",\"Value\":\""; int localKeyIndex = newMappingFileContents.IndexOf(mappingFileKey); string newCacheKey = newMappingFileContents.Substring(localKeyIndex + mappingFileKey.Length, GuidStringLength); // Validate the new objects root is on disk and uses the new key objectsRoot.ShouldNotExistOnDisk(this.fileSystem); string newObjectsRoot = GSDHelpers.GetPersistedGitObjectsRoot(enlistment.DotGSDRoot); newObjectsRoot.ShouldNotEqual(objectsRoot); newObjectsRoot.ShouldContain(newCacheKey); newObjectsRoot.ShouldBeADirectory(this.fileSystem); this.AlternatesFileShouldHaveGitObjectsRoot(enlistment); }
public void CloneToPathWithSpaces() { GSDFunctionalTestEnlistment enlistment = GSDFunctionalTestEnlistment.CloneAndMountEnlistmentWithSpacesInPath(GSDTestConfig.PathToGSD); enlistment.UnmountAndDeleteAll(); }