Skip to content

Commit

Permalink
Add integration tests for dotnet test (#46045)
Browse files Browse the repository at this point in the history
Co-authored-by: Amaury Levé <[email protected]>
  • Loading branch information
mariam-abdulla and Evangelink authored Jan 24, 2025
1 parent e2b601d commit 3322748
Show file tree
Hide file tree
Showing 94 changed files with 3,720 additions and 235 deletions.
1 change: 1 addition & 0 deletions eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<UsingToolMicrosoftNetCompilers Condition="'$(DotNetBuildSourceOnly)' == 'true'">true</UsingToolMicrosoftNetCompilers>
<MicrosoftIORedistPackageVersion>6.0.1</MicrosoftIORedistPackageVersion>
<FlagNetStandard1XDependencies Condition="'$(DotNetBuildSourceOnly)' == 'true'">true</FlagNetStandard1XDependencies>
<!-- This property is only used in the dotnet test integration tests. -->
<MicrosoftTestingPlatformVersion>1.6.0-preview.25072.4</MicrosoftTestingPlatformVersion>
</PropertyGroup>
<PropertyGroup Label="Servicing version information">
Expand Down
11 changes: 11 additions & 0 deletions src/Cli/Microsoft.DotNet.Cli.Utils/PathUtility.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Text.RegularExpressions;
using Microsoft.DotNet.Cli.Utils;
using NuGet.Configuration;

Expand Down Expand Up @@ -388,5 +389,15 @@ public static void EnsureAllPathsExist(

public static bool IsDirectory(this string path) =>
File.GetAttributes(path).HasFlag(FileAttributes.Directory);

public static string FixFilePath(string path)
{
return string.IsNullOrEmpty(path) || Path.DirectorySeparatorChar == '\\' ? path : path.Replace('\\', '/');
}

public static string GetDirectorySeparatorChar()
{
return Regex.Escape(Path.DirectorySeparatorChar.ToString());
}
}
}
5 changes: 4 additions & 1 deletion src/Cli/dotnet/commands/dotnet-test/CliConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ internal static class CliConstants

public const string TestSectionKey = "test";

public const string RestoreCommand = "restore";
public const string RestoreCommand = "Restore";
public const string BuildCommand = "Build";
public const string Configuration = "Configuration";
public const string RuntimeIdentifier = "RuntimeIdentifier";

public static readonly string[] ProjectExtensions = { ".proj", ".csproj", ".vbproj", ".fsproj" };
public static readonly string[] SolutionExtensions = { ".sln", ".slnx" };
Expand Down
213 changes: 141 additions & 72 deletions src/Cli/dotnet/commands/dotnet-test/MSBuildHandler.cs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/Cli/dotnet/commands/dotnet-test/Models.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ internal sealed record FlatException(string? ErrorMessage, string? ErrorType, st
internal sealed record FileArtifact(string? FullPath, string? DisplayName, string? Description, string? TestUid, string? TestDisplayName, string? SessionUid);

internal sealed record TestSession(byte? SessionType, string? SessionUid, string? ExecutionId);

internal record MSBuildBuildAndRestoreSettings(string[] Commands, string Configuration, string RuntimeIdentifier, bool AllowBinLog, string BinLogFileName);
}
4 changes: 2 additions & 2 deletions src/Cli/dotnet/commands/dotnet-test/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

namespace Microsoft.DotNet.Cli
{
internal record BuildConfigurationOptions(bool HasNoRestore, bool HasNoBuild, bool HasListTests, string Configuration, string Architecture);
internal record BuildConfigurationOptions(bool HasListTests, string Configuration, string Architecture);

internal record BuildPathsOptions(string ProjectPath, string SolutionPath, string DirectoryPath);
internal record BuildPathsOptions(string ProjectPath, string SolutionPath, string DirectoryPath, bool HasNoRestore, bool HasNoBuild, string Configuration, string RuntimeIdentifier);
}
21 changes: 8 additions & 13 deletions src/Cli/dotnet/commands/dotnet-test/SolutionAndProjectUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,22 @@ namespace Microsoft.DotNet.Cli
{
internal static class SolutionAndProjectUtility
{
public static bool TryGetProjectOrSolutionFilePath(string directory, out string projectOrSolutionFilePath, out bool isSolution)
public static (bool SolutionOrProjectFileFound, string Message) TryGetProjectOrSolutionFilePath(string directory, out string projectOrSolutionFilePath, out bool isSolution)
{
projectOrSolutionFilePath = string.Empty;
isSolution = false;

if (!Directory.Exists(directory))
{
return false;
return (false, string.Format(LocalizableStrings.CmdNonExistentDirectoryErrorDescription, directory));
}

var possibleSolutionPaths = GetSolutionFilePaths(directory);

// If more than a single sln file is found, an error is thrown since we can't determine which one to choose.
if (possibleSolutionPaths.Length > 1)
{
VSTestTrace.SafeWriteTrace(() => string.Format(CommonLocalizableStrings.MoreThanOneSolutionInDirectory, directory));
return false;
return (false, string.Format(CommonLocalizableStrings.MoreThanOneSolutionInDirectory, directory));
}

if (possibleSolutionPaths.Length == 1)
Expand All @@ -38,31 +37,27 @@ public static bool TryGetProjectOrSolutionFilePath(string directory, out string
{
projectOrSolutionFilePath = possibleSolutionPaths[0];
isSolution = true;
return true;
return (true, string.Empty);
}

VSTestTrace.SafeWriteTrace(() => LocalizableStrings.CmdMultipleProjectOrSolutionFilesErrorDescription);
return false;
return (false, LocalizableStrings.CmdMultipleProjectOrSolutionFilesErrorDescription);
}
else // If no solutions are found, look for a project file
{
string[] possibleProjectPath = GetProjectFilePaths(directory);

if (possibleProjectPath.Length == 0)
{
VSTestTrace.SafeWriteTrace(() => LocalizableStrings.CmdNoProjectOrSolutionFileErrorDescription);
return false;
return (false, LocalizableStrings.CmdNoProjectOrSolutionFileErrorDescription);
}

if (possibleProjectPath.Length == 1)
{
projectOrSolutionFilePath = possibleProjectPath[0];
return true;
return (true, string.Empty);
}

VSTestTrace.SafeWriteTrace(() => string.Format(CommonLocalizableStrings.MoreThanOneProjectInDirectory, directory));

return false;
return (false, string.Format(CommonLocalizableStrings.MoreThanOneSolutionInDirectory, directory));
}
}

Expand Down
36 changes: 15 additions & 21 deletions src/Cli/dotnet/commands/dotnet-test/TestApplication.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,8 @@ internal sealed class TestApplication : IDisposable
public event EventHandler<SessionEventArgs> SessionEventReceived;
public event EventHandler<ErrorEventArgs> ErrorReceived;
public event EventHandler<TestProcessExitEventArgs> TestProcessExited;
public event EventHandler<EventArgs> Run;
public event EventHandler<ExecutionEventArgs> ExecutionIdReceived;

private const string TestingPlatformVsTestBridgeRunSettingsFileEnvVar = "TESTINGPLATFORM_VSTESTBRIDGE_RUNSETTINGS_FILE";
private const string DLLExtension = "dll";

public Module Module => _module;

public TestApplication(Module module, List<string> args)
Expand All @@ -52,8 +48,6 @@ public void AddExecutionId(string executionId)

public async Task<int> RunAsync(bool hasFilterMode, bool enableHelp, BuildConfigurationOptions buildConfigurationOptions)
{
Run?.Invoke(this, EventArgs.Empty);

if (hasFilterMode && !ModulePathExists())
{
return 1;
Expand Down Expand Up @@ -89,11 +83,10 @@ private ProcessStartInfo CreateProcessStartInfo(bool hasFilterMode, bool isDll,
return processStartInfo;
}


private void WaitOnTestApplicationPipeConnectionLoop()
{
_cancellationToken.Cancel();
_testAppPipeConnectionLoop.Wait((int)TimeSpan.FromSeconds(30).TotalMilliseconds);
_testAppPipeConnectionLoop?.Wait((int)TimeSpan.FromSeconds(30).TotalMilliseconds);
}

private async Task WaitConnectionAsync(CancellationToken token)
Expand All @@ -109,9 +102,14 @@ private async Task WaitConnectionAsync(CancellationToken token)
_testAppPipeConnections.Add(pipeConnection);
}
}
catch (OperationCanceledException ex) when (ex.CancellationToken == token)
catch (OperationCanceledException ex)
{
// We are exiting
if (VSTestTrace.TraceEnabled)
{
string tokenType = ex.CancellationToken == token ? "internal token" : "external token";
VSTestTrace.SafeWriteTrace(() => $"WaitConnectionAsync() throws OperationCanceledException with {tokenType}");
}
}
catch (Exception ex)
{
Expand Down Expand Up @@ -212,7 +210,7 @@ private async Task<int> StartProcess(ProcessStartInfo processStartInfo)
{
if (VSTestTrace.TraceEnabled)
{
VSTestTrace.SafeWriteTrace(() => $"Updated args: {processStartInfo.Arguments}");
VSTestTrace.SafeWriteTrace(() => $"Test application arguments: {processStartInfo.Arguments}");
}

var process = Process.Start(processStartInfo);
Expand Down Expand Up @@ -262,15 +260,9 @@ private string BuildArgsWithDotnetRun(bool hasHelp, BuildConfigurationOptions bu

builder.Append($"{CliConstants.DotnetRunCommand} {TestingPlatformOptions.ProjectOption.Name} \"{_module.ProjectPath}\"");

if (buildConfigurationOptions.HasNoRestore)
{
builder.Append($" {TestingPlatformOptions.NoRestoreOption.Name}");
}

if (buildConfigurationOptions.HasNoBuild)
{
builder.Append($" {TestingPlatformOptions.NoBuildOption.Name}");
}
// Because we restored and built before in MSHandler, we will skip those with dotnet run
builder.Append($" {TestingPlatformOptions.NoRestoreOption.Name}");
builder.Append($" {TestingPlatformOptions.NoBuildOption.Name}");

if (buildConfigurationOptions.HasListTests)
{
Expand Down Expand Up @@ -382,12 +374,14 @@ public override string ToString()
if (!string.IsNullOrEmpty(_module.ProjectPath))
{
builder.Append($"Project: {_module.ProjectPath}");
};
}
;

if (!string.IsNullOrEmpty(_module.TargetFramework))
{
builder.Append($"Target Framework: {_module.TargetFramework}");
};
}
;

return builder.ToString();
}
Expand Down
4 changes: 0 additions & 4 deletions src/Cli/dotnet/commands/dotnet-test/TestCommandParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,9 +168,6 @@ private static bool IsTestingPlatformEnabled()

private static CliCommand ConstructCommand()
{
#if RELEASE
return GetVSTestCliCommand();
#else
bool isTestingPlatformEnabled = IsTestingPlatformEnabled();
string testingSdkName = isTestingPlatformEnabled ? "testingplatform" : "vstest";

Expand All @@ -184,7 +181,6 @@ private static CliCommand ConstructCommand()
}

throw new InvalidOperationException($"Testing sdk not supported: {testingSdkName}");
#endif
}

private static CliCommand GetTestingPlatformCliCommand()
Expand Down
Loading

0 comments on commit 3322748

Please sign in to comment.