Skip to content

Commit

Permalink
Extend GitRepoTests to allow include mode (#1331)
Browse files Browse the repository at this point in the history
* Extend GitRepoTests to allow include mode

The GitRepoTests can be initialized with a ValidateWorkingTree
mode that is currently a boolean. If enabled, we will add extra
checks to make sure the working tree of our virtual enlistment
matches the enlistment from a vanilla Git repo.

To extend this to the "include" mode, we need to first modify
this boolean into an enum and add it as an extra option.

Second, we need to be very careful about what we are comparing.
We will no longer virtualize outside of the included folders.
Be careful to include files in the root directory.

The functional tests can then be run with "--partial-mode" to
exercise only this option, which will isolate the test failures
to this setting AND keep the test suite from getting too slow.

Currently, the partial mode space is probably wider than
necessary and can be reduced in later iterations. This
does provide _some_ coverage.

Signed-off-by: Derrick Stolee <dstolee@microsoft.com>

* Use enum for passing into all tests instead of an int

* Clean up functional tests file system should extensions

* Rename argument to --include-mode to match the feature

* Add included folders below top level
  • Loading branch information
Kevin Willford committed Aug 5, 2019
1 parent 7fa910d commit 9728561
Show file tree
Hide file tree
Showing 25 changed files with 217 additions and 75 deletions.
2 changes: 1 addition & 1 deletion GVFS/GVFS.FunctionalTests/GVFS.FunctionalTests.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\GVFS.Build\GVFS.cs.props" />
<PropertyGroup>
<OutputType>Exe</OutputType>
Expand Down
21 changes: 18 additions & 3 deletions GVFS/GVFS.FunctionalTests/Program.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GVFS.FunctionalTests.Tools;
using GVFS.FunctionalTests.Properties;
using GVFS.FunctionalTests.Tools;
using GVFS.Tests;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -42,7 +43,13 @@ public static void Main(string[] args)
{
Console.WriteLine("Running the full suite of tests");

GVFSTestConfig.GitRepoTestsValidateWorkTree = DataSources.AllBools;
List<object[]> modes = new List<object[]>();
foreach (Settings.ValidateWorkingTreeMode mode in Enum.GetValues(typeof(Settings.ValidateWorkingTreeMode)))
{
modes.Add(new object[] { mode });
}

GVFSTestConfig.GitRepoTestsValidateWorkTree = modes.ToArray();

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
Expand All @@ -55,10 +62,18 @@ public static void Main(string[] args)
}
else
{
Settings.ValidateWorkingTreeMode validateMode = Settings.ValidateWorkingTreeMode.Full;

if (runner.HasCustomArg("--include-mode"))
{
validateMode = Settings.ValidateWorkingTreeMode.IncludeMode;
includeCategories.Add(Categories.GitCommands);
}

GVFSTestConfig.GitRepoTestsValidateWorkTree =
new object[]
{
new object[] { true }
new object[] { validateMode },
};

if (runner.HasCustomArg("--extra-only"))
Expand Down
7 changes: 7 additions & 0 deletions GVFS/GVFS.FunctionalTests/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ namespace GVFS.FunctionalTests.Properties
{
public static class Settings
{
public enum ValidateWorkingTreeMode
{
None = 0,
Full = 1,
IncludeMode = 2,
}

public static class Default
{
public static string CurrentDirectory { get; private set; }
Expand Down
60 changes: 53 additions & 7 deletions GVFS/GVFS.FunctionalTests/Should/FileSystemShouldExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,11 @@ public DirectoryAdapter WithDeepStructure(
FileSystemRunner fileSystem,
string otherPath,
bool ignoreCase = false,
bool compareContent = false)
bool compareContent = false,
string[] withinPrefixes = null)
{
otherPath.ShouldBeADirectory(this.runner);
CompareDirectories(fileSystem, otherPath, this.Path, ignoreCase, compareContent);
CompareDirectories(fileSystem, otherPath, this.Path, ignoreCase, compareContent, withinPrefixes);
return this;
}

Expand Down Expand Up @@ -251,12 +252,54 @@ public DirectoryInfo WithAttribute(FileAttributes attribute)
return info;
}

private static bool IsMatchedPath(FileSystemInfo info, string repoRoot, string[] prefixes)
{
if (prefixes == null || prefixes.Length == 0)
{
return true;
}

string localPath = info.FullName.Substring(repoRoot.Length + 1);

if (localPath.Equals(".git", StringComparison.OrdinalIgnoreCase))
{
// Include _just_ the .git folder.
// All sub-items are not included in the enumerator.
return true;
}

if (!localPath.Contains(System.IO.Path.DirectorySeparatorChar) &&
(info.Attributes & FileAttributes.Directory) != FileAttributes.Directory)
{
// If it is a file in the root folder, then include it.
return true;
}

foreach (string prefixDir in prefixes)
{
if (localPath.StartsWith(prefixDir, StringComparison.OrdinalIgnoreCase))
{
return true;
}

if (prefixDir.StartsWith(localPath, StringComparison.OrdinalIgnoreCase) &&
Directory.Exists(info.FullName))
{
// For example: localPath = "GVFS" and prefix is "GVFS\\GVFS".
return true;
}
}

return false;
}

private static void CompareDirectories(
FileSystemRunner fileSystem,
string expectedPath,
string actualPath,
bool ignoreCase,
bool compareContent)
bool compareContent,
string[] withinPrefixes)
{
IEnumerable<FileSystemInfo> expectedEntries = new DirectoryInfo(expectedPath).EnumerateFileSystemInfos("*", SearchOption.AllDirectories);
IEnumerable<FileSystemInfo> actualEntries = new DirectoryInfo(actualPath).EnumerateFileSystemInfos("*", SearchOption.AllDirectories);
Expand All @@ -265,6 +308,7 @@ private static void CompareDirectories(
IEnumerator<FileSystemInfo> expectedEnumerator = expectedEntries
.Where(x => !x.FullName.Contains(dotGitFolder))
.OrderBy(x => x.FullName)
.Where(x => IsMatchedPath(x, expectedPath, withinPrefixes))
.GetEnumerator();
IEnumerator<FileSystemInfo> actualEnumerator = actualEntries
.Where(x => !x.FullName.Contains(dotGitFolder))
Expand All @@ -279,7 +323,7 @@ private static void CompareDirectories(
bool nameIsEqual = false;
if (ignoreCase)
{
nameIsEqual = actualEnumerator.Current.Name.Equals(expectedEnumerator.Current.Name, StringComparison.OrdinalIgnoreCase);
nameIsEqual = actualEnumerator.Current.Name.Equals(expectedEnumerator.Current.Name, StringComparison.OrdinalIgnoreCase);
}
else
{
Expand All @@ -297,6 +341,7 @@ private static void CompareDirectories(
if (Directory.GetFileSystemEntries(expectedEnumerator.Current.FullName, "*", SearchOption.TopDirectoryOnly).Length == 0)
{
expectedMoved = expectedEnumerator.MoveNext();

continue;
}
}
Expand All @@ -306,15 +351,15 @@ private static void CompareDirectories(

if ((expectedEnumerator.Current.Attributes & FileAttributes.Directory) == FileAttributes.Directory)
{
(actualEnumerator.Current.Attributes & FileAttributes.Directory).ShouldEqual(FileAttributes.Directory, $"expected path: {expectedEnumerator.Current.FullName} actual path: {actualEnumerator.Current.FullName}");
(actualEnumerator.Current.Attributes & FileAttributes.Directory).ShouldEqual(FileAttributes.Directory, $"expected directory path: {expectedEnumerator.Current.FullName} actual file path: {actualEnumerator.Current.FullName}");
}
else
{
(actualEnumerator.Current.Attributes & FileAttributes.Directory).ShouldNotEqual(FileAttributes.Directory, $"expected path: {expectedEnumerator.Current.FullName} actual path: {actualEnumerator.Current.FullName}");
(actualEnumerator.Current.Attributes & FileAttributes.Directory).ShouldNotEqual(FileAttributes.Directory, $"expected file path: {expectedEnumerator.Current.FullName} actual directory path: {actualEnumerator.Current.FullName}");

FileInfo expectedFileInfo = (expectedEnumerator.Current as FileInfo).ShouldNotBeNull();
FileInfo actualFileInfo = (actualEnumerator.Current as FileInfo).ShouldNotBeNull();
actualFileInfo.Length.ShouldEqual(expectedFileInfo.Length);
actualFileInfo.Length.ShouldEqual(expectedFileInfo.Length, $"File lengths do not agree expected: {expectedEnumerator.Current.FullName} = {expectedFileInfo.Length} actual: {actualEnumerator.Current.FullName} = {actualFileInfo.Length}");

if (compareContent)
{
Expand All @@ -327,6 +372,7 @@ private static void CompareDirectories(
}

StringBuilder errorEntries = new StringBuilder();

if (expectedMoved)
{
do
Expand Down
5 changes: 3 additions & 2 deletions GVFS/GVFS.FunctionalTests/Tests/GitCommands/AddStageTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GVFS.FunctionalTests.Tools;
using GVFS.FunctionalTests.Properties;
using GVFS.FunctionalTests.Tools;
using NUnit.Framework;
using System.IO;
using System.Threading;
Expand All @@ -9,7 +10,7 @@ namespace GVFS.FunctionalTests.Tests.GitCommands
[Category(Categories.GitCommands)]
public class AddStageTests : GitRepoTests
{
public AddStageTests(bool validateWorkingTree)
public AddStageTests(Settings.ValidateWorkingTreeMode validateWorkingTree)
: base(enlistmentPerTest: false, validateWorkingTree: validateWorkingTree)
{
}
Expand Down
9 changes: 5 additions & 4 deletions GVFS/GVFS.FunctionalTests/Tests/GitCommands/CheckoutTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GVFS.FunctionalTests.Should;
using GVFS.FunctionalTests.Properties;
using GVFS.FunctionalTests.Should;
using GVFS.FunctionalTests.Tools;
using GVFS.Tests.Should;
using Microsoft.Win32.SafeHandles;
Expand All @@ -15,7 +16,7 @@ namespace GVFS.FunctionalTests.Tests.GitCommands
[Category(Categories.GitCommands)]
public class CheckoutTests : GitRepoTests
{
public CheckoutTests(bool validateWorkingTree)
public CheckoutTests(Settings.ValidateWorkingTreeMode validateWorkingTree)
: base(enlistmentPerTest: true, validateWorkingTree: validateWorkingTree)
{
}
Expand Down Expand Up @@ -238,11 +239,11 @@ public void CheckoutBranchAfterReadingAllFilesAndVerifyContentsCorrect()

this.ValidateGitCommand("checkout " + GitRepoTests.ConflictTargetBranch);
this.Enlistment.RepoRoot.ShouldBeADirectory(this.FileSystem)
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath, compareContent: true);
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath, compareContent: true, withinPrefixes: this.pathPrefixes);

this.ValidateGitCommand("checkout " + GitRepoTests.ConflictSourceBranch);
this.Enlistment.RepoRoot.ShouldBeADirectory(this.FileSystem)
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath, compareContent: true);
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath, compareContent: true, withinPrefixes: this.pathPrefixes);

// Verify modified paths contents
GVFSHelpers.ModifiedPathsContentsShouldEqual(this.Enlistment, this.FileSystem, "A .gitattributes" + GVFSHelpers.ModifiedPathsNewLine);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using NUnit.Framework;
using GVFS.FunctionalTests.Properties;
using NUnit.Framework;

namespace GVFS.FunctionalTests.Tests.GitCommands
{
[TestFixtureSource(typeof(GitRepoTests), nameof(GitRepoTests.ValidateWorkingTree))]
[Category(Categories.GitCommands)]
public class CherryPickConflictTests : GitRepoTests
{
public CherryPickConflictTests(bool validateWorkingTree)
public CherryPickConflictTests(Settings.ValidateWorkingTreeMode validateWorkingTree)
: base(enlistmentPerTest: true, validateWorkingTree: validateWorkingTree)
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GVFS.FunctionalTests.Should;
using GVFS.FunctionalTests.Properties;
using GVFS.FunctionalTests.Should;
using GVFS.FunctionalTests.Tools;
using NUnit.Framework;
using System.IO;
Expand All @@ -13,7 +14,7 @@ public class CreatePlaceholderTests : GitRepoTests
{
private static readonly string FileToRead = Path.Combine("GVFS", "GVFS", "Program.cs");

public CreatePlaceholderTests(bool validateWorkingTree)
public CreatePlaceholderTests(Settings.ValidateWorkingTreeMode validateWorkingTree)
: base(enlistmentPerTest: true, validateWorkingTree: validateWorkingTree)
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
using GVFS.FunctionalTests.Should;
using GVFS.FunctionalTests.Tools;
using GVFS.FunctionalTests.Properties;
using GVFS.FunctionalTests.Should;
using NUnit.Framework;

namespace GVFS.FunctionalTests.Tests.GitCommands
Expand All @@ -8,7 +8,7 @@ namespace GVFS.FunctionalTests.Tests.GitCommands
[Category(Categories.GitCommands)]
public class DeleteEmptyFolderTests : GitRepoTests
{
public DeleteEmptyFolderTests(bool validateWorkingTree)
public DeleteEmptyFolderTests(Settings.ValidateWorkingTreeMode validateWorkingTree)
: base(enlistmentPerTest: true, validateWorkingTree: validateWorkingTree)
{
}
Expand All @@ -20,7 +20,7 @@ public void VerifyResetHardDeletesEmptyFolders()

this.RunGitCommand("reset --hard HEAD");
this.Enlistment.RepoRoot.ShouldBeADirectory(this.FileSystem)
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath);
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath, withinPrefixes: this.pathPrefixes);
}

[TestCase]
Expand All @@ -30,7 +30,7 @@ public void VerifyCleanDeletesEmptyFolders()

this.RunGitCommand("clean -fd");
this.Enlistment.RepoRoot.ShouldBeADirectory(this.FileSystem)
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath);
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath, withinPrefixes: this.pathPrefixes);
}

private void SetupFolderDeleteTest()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NUnit.Framework;
using GVFS.FunctionalTests.Properties;
using NUnit.Framework;

namespace GVFS.FunctionalTests.Tests.GitCommands
{
Expand All @@ -10,7 +11,7 @@ public class EnumerationMergeTest : GitRepoTests
// enumeration when they don't fit in a user's buffer
private const string EnumerationReproCommitish = "FunctionalTests/20170602";

public EnumerationMergeTest(bool validateWorkingTree)
public EnumerationMergeTest(Settings.ValidateWorkingTreeMode validateWorkingTree)
: base(enlistmentPerTest: true, validateWorkingTree: validateWorkingTree)
{
}
Expand Down
13 changes: 7 additions & 6 deletions GVFS/GVFS.FunctionalTests/Tests/GitCommands/GitCommandsTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using GVFS.FunctionalTests.Should;
using GVFS.FunctionalTests.Properties;
using GVFS.FunctionalTests.Should;
using GVFS.FunctionalTests.Tools;
using GVFS.Tests.Should;
using NUnit.Framework;
Expand All @@ -12,11 +13,11 @@ namespace GVFS.FunctionalTests.Tests.GitCommands
[Category(Categories.GitCommands)]
public class GitCommandsTests : GitRepoTests
{
public const string TopLevelFolderToCreate = "level1";
private const string EncodingFileFolder = "FilenameEncoding";
private const string EncodingFilename = "ريلٌأكتوبرûمارسأغسطسºٰٰۂْٗ۵ريلٌأك.txt";
private const string ContentWhenEditingFile = "// Adding a comment to the file";
private const string UnknownTestName = "Unknown";
private const string TopLevelFolderToCreate = "level1";
private const string SubFolderToCreate = "level2";

private static readonly string EditFilePath = Path.Combine("GVFS", "GVFS.Common", "GVFSContext.cs");
Expand All @@ -26,7 +27,7 @@ public class GitCommandsTests : GitRepoTests
private static readonly string RenameFolderPathFrom = Path.Combine("GVFS", "GVFS.Common", "PrefetchPacks");
private static readonly string RenameFolderPathTo = Path.Combine("GVFS", "GVFS.Common", "PrefetchPacksRenamed");

public GitCommandsTests(bool validateWorkingTree)
public GitCommandsTests(Settings.ValidateWorkingTreeMode validateWorkingTree)
: base(enlistmentPerTest: false, validateWorkingTree: validateWorkingTree)
{
}
Expand Down Expand Up @@ -586,7 +587,7 @@ public void AddFileCommitThenDeleteAndCommit()
this.RunGitCommand("commit -m \"Delete file for AddFileCommitThenDeleteAndCommit\"");
this.ValidateGitCommand("checkout tests/functional/AddFileCommitThenDeleteAndCommit_before");
this.Enlistment.RepoRoot.ShouldBeADirectory(this.FileSystem)
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath);
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath, withinPrefixes: this.pathPrefixes);
this.ValidateGitCommand("checkout tests/functional/AddFileCommitThenDeleteAndCommit_after");
}

Expand Down Expand Up @@ -674,7 +675,7 @@ public void AddFolderAndFileCommitThenResetSoftAndResetMixed()
this.ValidateGitCommand("checkout -b tests/functional/AddFileCommitThenDeleteAndResetSoft");
string folderPath = "test_folder";
this.CreateFolder(folderPath);
string filePath = Path.Combine(folderPath + "testfile.txt");
string filePath = Path.Combine(folderPath, "testfile.txt");
this.CreateFile("Some new content for the file", filePath);
this.ValidateGitCommand("status");
this.ValidateGitCommand("add .");
Expand Down Expand Up @@ -1080,7 +1081,7 @@ private void CommitChangesSwitchBranchSwitchBack(Action fileSystemAction, [Calle
this.RunGitCommand("commit -m \"Change for {0}\"", branch);
this.ValidateGitCommand("checkout " + this.ControlGitRepo.Commitish);
this.Enlistment.RepoRoot.ShouldBeADirectory(this.FileSystem)
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath);
.WithDeepStructure(this.FileSystem, this.ControlGitRepo.RootPath, withinPrefixes: this.pathPrefixes);

this.ValidateGitCommand("checkout {0}", branch);
}
Expand Down
Loading

0 comments on commit 9728561

Please sign in to comment.