Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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");
        }
Пример #5
0
        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);
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
                }
            }
        }
Пример #9
0
 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();
 }
Пример #10
0
 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();
     }
 }
Пример #11
0
        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]);
            }
        }
Пример #12
0
        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);
     }
 }
Пример #14
0
        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]);
                }
            }
        }
Пример #15
0
        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);
        }
Пример #16
0
        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");
        }
Пример #17
0
        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");
        }
Пример #18
0
        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();
        }
Пример #19
0
        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));
        }
Пример #20
0
        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);
        }
Пример #21
0
        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);
        }
Пример #22
0
        public void CloneToPathWithSpaces()
        {
            GSDFunctionalTestEnlistment enlistment = GSDFunctionalTestEnlistment.CloneAndMountEnlistmentWithSpacesInPath(GSDTestConfig.PathToGSD);

            enlistment.UnmountAndDeleteAll();
        }