Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .azure-pipelines/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,13 @@ extends:
${{ dim.arch }}
displayName: 'Run unit tests'

- task: PowerShell@2
displayName: 'Run local functional components'
inputs:
pwsh: true
filePath: '$(Build.SourcesDirectory)\scripts\RunLocalComponentTests-Dev.ps1'
arguments: '-Configuration $(BuildConfiguration) -Arch ${{ dim.arch }}'

# ESRP signing of the standalone binaries (Payload + FastFetch).
# The installer hasn't been built yet, so it can be packaged from
# signed binaries in a single Inno Setup pass.
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ jobs:
shell: cmd
run: src\scripts\CreateBuildArtifacts.bat ${{ matrix.configuration }} artifacts ${{ matrix.architecture }}

- name: Run local functional components
if: steps.skip.outputs.result != 'true'
shell: pwsh
run: src\scripts\RunLocalComponentTests-Dev.ps1 -Configuration ${{ matrix.configuration }} -Arch ${{ matrix.architecture }}

- name: Upload functional tests drop
if: steps.skip.outputs.result != 'true'
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
Expand Down
15 changes: 13 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -279,10 +279,19 @@ The design review process is as follows:

Comprehensive tests are essential for maintaining the health and quality of the product. For more details on writing tests see [Authoring Tests](https://github.com/Microsoft/VFSForGit/blob/master/AuthoringTests.md).

- *Functional tests are black-box tests and should not build against any VFS4G product code*
- *Keep end-to-end functional tests black-box*

Keeping the code separate helps ensure that bugs in the product code do not compromise the integrity of the functional tests.

Local component tests in `GVFS.FunctionalTests.Tests.LocalComponents` can call product APIs to verify real Git, process, HTTP, and named-pipe behavior.
These tests use the existing functional runner and service lifecycle, but do not require a mounted enlistment or a remote repository.
Keep their dependencies local and isolate temporary files, configuration, and environment changes.

Unit tests must not start external programs or use real network or named-pipe connections.
Native hook executable tests are an exception.
Unit tests can use isolated temporary files and the repository-built libgit2 library.
Keep pure policy, parsing, and controlled-stream tests in the unit suite.

### C# Unit Tests

- *Add `ExceptionExpected` to unit tests that are expected to have exceptions*
Expand All @@ -298,4 +307,6 @@ The design review process is as follows:

- *Use a `mock` prefix for absolute file system paths and URLs*

The unit tests should not touch the real file system nor should they reach out to any real URLs. Using `mock:\\` and `mock://` ensures that any product code that was not properly mocked will not interact with the real file system or attempt to contact a real URL.
Use `mock:\\` and `mock://` when a test does not require real files.
This convention prevents unexpected file access or network requests when product code is not fully mocked.
Filesystem-only tests must use an isolated temporary directory and remove their files after each test.
35 changes: 0 additions & 35 deletions GVFS/GVFS.CommandLine.Tests/GVFSMountExitCodeTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
using System;
using System.CommandLine;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using GVFS.Common;
using GVFS.PlatformLoader;
using NUnit.Framework;
Expand All @@ -28,38 +26,5 @@ public void InvalidEnlistment_ReturnsGenericErrorExitCode()

Assert.That(exitCode, Is.EqualTo((int)ReturnCode.GenericError));
}

[Test]
public void InvalidEnlistmentProcess_ReturnsGenericErrorExitCode()
{
string nonExistentPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
string mountOutputDirectory = AppContext.BaseDirectory.Replace(
"GVFS.CommandLine.Tests",
"GVFS.Mount",
StringComparison.OrdinalIgnoreCase);
ProcessStartInfo processInfo = new ProcessStartInfo
{
FileName = Path.Combine(mountOutputDirectory, "GVFS.Mount.exe"),
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
UseShellExecute = false,
};
processInfo.ArgumentList.Add(nonExistentPath);

using (Process process = Process.Start(processInfo))
{
Task<string> output = process.StandardOutput.ReadToEndAsync();
Task<string> errors = process.StandardError.ReadToEndAsync();

process.WaitForExit();
Task.WaitAll(output, errors);

Assert.That(
process.ExitCode,
Is.EqualTo((int)ReturnCode.GenericError),
$"stdout: {output.Result}{Environment.NewLine}stderr: {errors.Result}");
}
}
}
}
1 change: 1 addition & 0 deletions GVFS/GVFS.Common/InternalsVisibleTo.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("GVFS.UnitTests")]
[assembly: InternalsVisibleTo("GVFS.FunctionalTests")]
2 changes: 1 addition & 1 deletion GVFS/GVFS.FunctionalTests/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ public class Program
{
public static void Main(string[] args)
{
Properties.Settings.Default.Initialize();
GVFSPlatformLoader.Initialize();
Properties.Settings.Default.Initialize();

GVFSTestConfig.IsDevMode = Environment.GetEnvironmentVariable("GVFS_FUNCTIONAL_TEST_DEV_MODE") == "1";

Expand Down
5 changes: 3 additions & 2 deletions GVFS/GVFS.FunctionalTests/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,9 @@ public static void Initialize()
PathToGVFSService = @"C:\Program Files\VFS for Git\GVFS.Service.exe";
}

PathToGit = @"C:\Program Files\Git\cmd\git.exe";
PathToBash = @"C:\Program Files\Git\bin\bash.exe";
PathToGit = GVFS.Common.GVFSPlatform.Instance.GitInstallation.GetInstalledGitBinPath()
?? throw new FileNotFoundException("Functional tests require the Git installation that GVFS uses.");
PathToBash = Path.Combine(Path.GetDirectoryName(Path.GetDirectoryName(PathToGit)), "bin", "bash.exe");
}
}
}
Expand Down
Loading
Loading