|
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections.Generic;
#if !NET
using System.Diagnostics;
#endif
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.TestPlatform.VsTestConsole.TranslationLayer.Interfaces;
using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Helpers;
using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing;
using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing.Interfaces;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces;
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions;
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces;
using Microsoft.VisualStudio.TestPlatform.VsTestConsole.TranslationLayer;
using Microsoft.VisualStudio.TestPlatform.VsTestConsole.TranslationLayer.Interfaces;
using CommunicationUtilitiesResources = Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Resources.Resources;
using CoreUtilitiesConstants = Microsoft.VisualStudio.TestPlatform.CoreUtilities.Constants;
namespace Microsoft.TestPlatform.VsTestConsole.TranslationLayer;
/// <summary>
/// An implementation of <see cref="IVsTestConsoleWrapper"/> to invoke test operations
/// via the <c>vstest.console</c> test runner.
/// </summary>
public class VsTestConsoleWrapper : IVsTestConsoleWrapper
{
private readonly IProcessManager _vstestConsoleProcessManager;
private readonly ITranslationLayerRequestSender _requestSender;
private readonly IProcessHelper _processHelper;
private bool _sessionStarted;
/// <summary>
/// Path to additional extensions to reinitialize vstest.console
/// </summary>
private IEnumerable<string> _pathToAdditionalExtensions;
/// <summary>
/// Additional parameters for vstest.console.exe
/// </summary>
private readonly ConsoleParameters _consoleParameters;
private readonly ITestPlatformEventSource _testPlatformEventSource;
/// <summary>
/// Initializes a new instance of the <see cref="VsTestConsoleWrapper"/> class.
/// </summary>
///
/// <param name="vstestConsolePath">
/// Path to the test runner <c>vstest.console.exe</c>.
/// </param>
public VsTestConsoleWrapper(
string vstestConsolePath)
: this(
vstestConsolePath,
ConsoleParameters.Default)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="VsTestConsoleWrapper"/> class.
/// </summary>
///
/// <param name="vstestConsolePath">Path to the test runner <c>vstest.console.exe</c>.</param>
/// <param name="consoleParameters">The parameters to be passed onto the runner process.</param>
public VsTestConsoleWrapper(
string vstestConsolePath,
ConsoleParameters consoleParameters)
: this(
new VsTestConsoleRequestSender(),
new VsTestConsoleProcessManager(vstestConsolePath),
consoleParameters,
TestPlatformEventSource.Instance,
new ProcessHelper())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="VsTestConsoleWrapper"/> class.
/// </summary>
///
/// <remarks>Defined for testing purposes.</remarks>
///
/// <param name="vstestConsolePath">Path to the test runner <c>vstest.console.exe</c>.</param>
/// <param name="dotnetExePath">Path to dotnet exe, needed for CI builds.</param>
/// <param name="consoleParameters">The parameters to be passed onto the runner process.</param>
internal VsTestConsoleWrapper(
string vstestConsolePath,
string dotnetExePath,
ConsoleParameters consoleParameters)
: this(
new VsTestConsoleRequestSender(),
new VsTestConsoleProcessManager(vstestConsolePath, dotnetExePath),
consoleParameters,
TestPlatformEventSource.Instance,
new ProcessHelper())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="VsTestConsoleWrapper"/> class.
/// </summary>
///
/// <param name="requestSender">Sender for test messages.</param>
/// <param name="processManager">Process manager.</param>
/// <param name="consoleParameters">The parameters to be passed onto the runner process.</param>
/// <param name="testPlatformEventSource">Performance event source.</param>
/// <param name="processHelper">Helper for process related utilities.</param>
internal VsTestConsoleWrapper(
ITranslationLayerRequestSender requestSender,
IProcessManager processManager,
ConsoleParameters consoleParameters,
ITestPlatformEventSource testPlatformEventSource,
IProcessHelper processHelper)
{
_requestSender = requestSender;
_vstestConsoleProcessManager = processManager;
_consoleParameters = consoleParameters;
_testPlatformEventSource = testPlatformEventSource;
_processHelper = processHelper;
_pathToAdditionalExtensions = new List<string>();
_vstestConsoleProcessManager.ProcessExited += (sender, args) => _requestSender.OnProcessExited();
_sessionStarted = false;
// TODO: this is writing into the same file in integration tests (there is just 1 eqTrace for whole process)
// figure out how to make it useful. The logs helped a bit in debugging, but not by much.
//if (_consoleParameters.TraceLevel == TraceLevel.Verbose && !string.IsNullOrWhiteSpace(_consoleParameters.LogFilePath))
//{
// var logFilePath = Path.ChangeExtension(
// _consoleParameters.LogFilePath,
// string.Format(
// CultureInfo.InvariantCulture,
// "translationLayer.{0}_{1}{2}",
// DateTime.Now.ToString("yy-MM-dd_HH-mm-ss_fffff", CultureInfo.CurrentCulture),
// new PlatformEnvironment().GetCurrentManagedThreadId(),
// Path.GetExtension(_consoleParameters.LogFilePath))
// );
// EqtTrace.InitializeTrace(logFilePath, PlatformTraceLevel.Verbose);
//}
}
#region IVsTestConsoleWrapper
/// <inheritdoc/>
public void StartSession()
{
EqtTrace.Info("VsTestConsoleWrapper.StartSession: Starting VsTestConsoleWrapper session.");
_testPlatformEventSource.TranslationLayerInitializeStart();
// Start communication
var port = _requestSender.InitializeCommunication();
if (port > 0)
{
// Fill the parameters
#if NET
_consoleParameters.ParentProcessId = Environment.ProcessId;
#else
using (var process = Process.GetCurrentProcess())
_consoleParameters.ParentProcessId = process.Id;
#endif
_consoleParameters.PortNumber = port;
// Start vstest.console.exe process
_vstestConsoleProcessManager.StartProcess(_consoleParameters);
}
else
{
// Close the sender as it failed to host server
_requestSender.Close();
throw new TransationLayerException("Error hosting communication channel");
}
}
/// <inheritdoc/>
[Obsolete("This API is not final yet and is subject to changes.", false)]
public ITestSession? StartTestSession(
IList<string> sources,
string? runSettings,
ITestSessionEventsHandler eventsHandler)
{
return StartTestSession(
sources,
runSettings,
options: null,
eventsHandler);
}
/// <inheritdoc/>
[Obsolete("This API is not final yet and is subject to changes.", false)]
public ITestSession? StartTestSession(
IList<string> sources,
string? runSettings,
TestPlatformOptions? options,
ITestSessionEventsHandler eventsHandler)
{
return StartTestSession(
sources,
runSettings,
options,
eventsHandler,
testHostLauncher: null);
}
/// <inheritdoc/>
[Obsolete("This API is not final yet and is subject to changes.", false)]
public ITestSession? StartTestSession(
IList<string> sources,
string? runSettings,
TestPlatformOptions? options,
ITestSessionEventsHandler eventsHandler,
ITestHostLauncher? testHostLauncher)
{
_testPlatformEventSource.TranslationLayerStartTestSessionStart();
EnsureInitialized();
var testSessionInfo = _requestSender.StartTestSession(
sources,
runSettings,
options,
eventsHandler,
testHostLauncher);
return (testSessionInfo != null)
? new TestSession(
testSessionInfo,
eventsHandler,
this)
: null;
}
/// <inheritdoc/>
[Obsolete("This API is not final yet and is subject to changes.", false)]
public bool StopTestSession(
TestSessionInfo? testSessionInfo,
ITestSessionEventsHandler eventsHandler)
{
return StopTestSession(
testSessionInfo,
options: null,
eventsHandler);
}
/// <inheritdoc/>
[Obsolete("This API is not final yet and is subject to changes.", false)]
public bool StopTestSession(
TestSessionInfo? testSessionInfo,
TestPlatformOptions? options,
ITestSessionEventsHandler eventsHandler)
{
_testPlatformEventSource.TranslationLayerStopTestSessionStart();
EnsureInitialized();
return _requestSender.StopTestSession(
testSessionInfo,
options,
eventsHandler);
}
/// <inheritdoc/>
public void InitializeExtensions(IEnumerable<string> pathToAdditionalExtensions)
{
EnsureInitialized();
_pathToAdditionalExtensions = pathToAdditionalExtensions.ToList();
_requestSender.InitializeExtensions(_pathToAdditionalExtensions);
}
/// <inheritdoc/>
public void DiscoverTests(
IEnumerable<string> sources,
string? discoverySettings,
ITestDiscoveryEventsHandler discoveryEventsHandler)
{
DiscoverTests(
sources,
discoverySettings,
options: null,
discoveryEventsHandler: new DiscoveryEventsHandleConverter(discoveryEventsHandler));
}
/// <inheritdoc/>
public void DiscoverTests(
IEnumerable<string> sources,
string? discoverySettings,
TestPlatformOptions? options,
ITestDiscoveryEventsHandler2 discoveryEventsHandler)
{
DiscoverTests(
sources,
discoverySettings,
options,
testSessionInfo: null,
discoveryEventsHandler);
}
/// <inheritdoc/>
public void DiscoverTests(
IEnumerable<string> sources,
string? discoverySettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestDiscoveryEventsHandler2 discoveryEventsHandler)
{
_testPlatformEventSource.TranslationLayerDiscoveryStart();
EnsureInitialized();
_requestSender.DiscoverTests(
sources,
discoverySettings,
options,
testSessionInfo,
discoveryEventsHandler);
}
/// <inheritdoc/>
public void CancelDiscovery()
{
_requestSender.CancelDiscovery();
}
/// <inheritdoc/>
public void RunTests(
IEnumerable<string> sources,
string? runSettings,
ITestRunEventsHandler testRunEventsHandler)
{
RunTests(
sources,
runSettings,
options: null,
testRunEventsHandler: testRunEventsHandler);
}
/// <inheritdoc/>
public void RunTests(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
ITestRunEventsHandler testRunEventsHandler)
{
RunTests(
sources,
runSettings,
options,
testSessionInfo: null,
testRunEventsHandler);
}
/// <inheritdoc/>
public void RunTests(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler)
{
RunTests(
sources,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
new NoOpTelemetryEventsHandler());
}
/// <inheritdoc/>
public void RunTests(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITelemetryEventsHandler telemetryEventsHandler)
{
var sourceList = sources.ToList();
_testPlatformEventSource.TranslationLayerExecutionStart(
0,
sourceList.Count,
0,
runSettings ?? string.Empty);
EnsureInitialized();
_requestSender.StartTestRun(
sourceList,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
telemetryEventsHandler);
}
/// <inheritdoc/>
public void RunTests(
IEnumerable<TestCase> testCases,
string? runSettings,
ITestRunEventsHandler testRunEventsHandler)
{
RunTests(
testCases,
runSettings,
options: null,
testRunEventsHandler);
}
/// <inheritdoc/>
public void RunTests(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
ITestRunEventsHandler testRunEventsHandler)
{
RunTests(
testCases,
runSettings,
options,
testSessionInfo: null,
testRunEventsHandler);
}
/// <inheritdoc/>
public void RunTests(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler)
{
RunTests(
testCases,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
new NoOpTelemetryEventsHandler());
}
/// <inheritdoc/>
public void RunTests(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITelemetryEventsHandler telemetryEventsHandler)
{
var testCaseList = testCases.ToList();
_testPlatformEventSource.TranslationLayerExecutionStart(
0,
0,
testCaseList.Count,
runSettings ?? string.Empty);
EnsureInitialized();
_requestSender.StartTestRun(
testCaseList,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
telemetryEventsHandler);
}
/// <inheritdoc/>
public void RunTestsWithCustomTestHost(
IEnumerable<string> sources,
string? runSettings,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
RunTestsWithCustomTestHost(
sources,
runSettings,
options: null,
testRunEventsHandler: testRunEventsHandler,
customTestHostLauncher: customTestHostLauncher);
}
/// <inheritdoc/>
public void RunTestsWithCustomTestHost(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
RunTestsWithCustomTestHost(
sources,
runSettings,
options,
testSessionInfo: null,
testRunEventsHandler,
customTestHostLauncher);
}
/// <inheritdoc/>
public void RunTestsWithCustomTestHost(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
RunTestsWithCustomTestHost(
sources,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
new NoOpTelemetryEventsHandler(),
customTestHostLauncher);
}
/// <inheritdoc/>
public void RunTestsWithCustomTestHost(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITelemetryEventsHandler telemetryEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
var sourceList = sources.ToList();
_testPlatformEventSource.TranslationLayerExecutionStart(
1,
sourceList.Count,
0,
runSettings ?? string.Empty);
EnsureInitialized();
_requestSender.StartTestRunWithCustomHost(
sourceList,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
telemetryEventsHandler,
customTestHostLauncher);
}
/// <inheritdoc/>
public void RunTestsWithCustomTestHost(
IEnumerable<TestCase> testCases,
string? runSettings,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
RunTestsWithCustomTestHost(
testCases,
runSettings,
options: null,
testRunEventsHandler,
customTestHostLauncher);
}
/// <inheritdoc/>
public void RunTestsWithCustomTestHost(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
RunTestsWithCustomTestHost(
testCases,
runSettings,
options,
testSessionInfo: null,
testRunEventsHandler,
customTestHostLauncher);
}
/// <inheritdoc/>
public void RunTestsWithCustomTestHost(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
RunTestsWithCustomTestHost(
testCases,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
new NoOpTelemetryEventsHandler(),
customTestHostLauncher);
}
/// <inheritdoc/>
public void RunTestsWithCustomTestHost(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITelemetryEventsHandler telemetryEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
var testCaseList = testCases.ToList();
_testPlatformEventSource.TranslationLayerExecutionStart(
1,
0,
testCaseList.Count,
runSettings ?? string.Empty);
EnsureInitialized();
_requestSender.StartTestRunWithCustomHost(
testCaseList,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
telemetryEventsHandler,
customTestHostLauncher);
}
/// <inheritdoc/>
public void CancelTestRun()
{
_requestSender.CancelTestRun();
}
/// <inheritdoc/>
public void AbortTestRun()
{
_requestSender.AbortTestRun();
}
/// <inheritdoc/>
public void EndSession()
{
EqtTrace.Info($"VsTestConsoleWrapper.EndSession: Ending VsTestConsoleWrapper session - process id:{_vstestConsoleProcessManager.ProcessId}");
_requestSender.EndSession();
_requestSender.Close();
EqtTrace.Info("VsTestConsoleWrapper.EndSession: Ended VsTestConsoleWrapper session");
// If vstest.console is still hanging around, it should be explicitly killed.
_vstestConsoleProcessManager.ShutdownProcess();
_sessionStarted = false;
}
#endregion
#region IVsTestConsoleWrapperAsync
/// <inheritdoc/>
public async Task StartSessionAsync()
{
EqtTrace.Info("VsTestConsoleWrapperAsync.StartSessionAsync: Starting VsTestConsoleWrapper session");
_testPlatformEventSource.TranslationLayerInitializeStart();
var timeout = EnvironmentHelper.GetConnectionTimeout();
// Start communication
var port = await _requestSender.InitializeCommunicationAsync(timeout * 1000).ConfigureAwait(false);
if (port > 0)
{
// Fill the parameters
#if NET
_consoleParameters.ParentProcessId = Environment.ProcessId;
#else
using (var process = Process.GetCurrentProcess())
_consoleParameters.ParentProcessId = process.Id;
#endif
_consoleParameters.PortNumber = port;
// Start vstest.console.exe process
_vstestConsoleProcessManager.StartProcess(_consoleParameters);
}
else
{
// Close the sender as it failed to host server
_requestSender.Close();
throw new TransationLayerException("Error hosting communication channel and connecting to console");
}
}
/// <inheritdoc/>
[Obsolete("This API is not final yet and is subject to changes.", false)]
public async Task<ITestSession?> StartTestSessionAsync(
IList<string> sources,
string? runSettings,
ITestSessionEventsHandler eventsHandler)
{
return await StartTestSessionAsync(
sources,
runSettings,
options: null,
eventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
[Obsolete("This API is not final yet and is subject to changes.", false)]
public async Task<ITestSession?> StartTestSessionAsync(
IList<string> sources,
string? runSettings,
TestPlatformOptions? options,
ITestSessionEventsHandler eventsHandler)
{
return await StartTestSessionAsync(
sources,
runSettings,
options,
eventsHandler,
testHostLauncher: null).ConfigureAwait(false);
}
/// <inheritdoc/>
[Obsolete("This API is not final yet and is subject to changes.", false)]
public async Task<ITestSession?> StartTestSessionAsync(
IList<string> sources,
string? runSettings,
TestPlatformOptions? options,
ITestSessionEventsHandler eventsHandler,
ITestHostLauncher? testHostLauncher)
{
_testPlatformEventSource.TranslationLayerStartTestSessionStart();
await EnsureInitializedAsync().ConfigureAwait(false);
var testSessionInfo = await _requestSender.StartTestSessionAsync(
sources,
runSettings,
options,
eventsHandler,
testHostLauncher).ConfigureAwait(false);
return testSessionInfo != null
? new TestSession(
testSessionInfo,
eventsHandler,
this)
: null;
}
/// <inheritdoc/>
[Obsolete("This API is not final yet and is subject to changes.", false)]
public async Task<bool> StopTestSessionAsync(
TestSessionInfo? testSessionInfo,
ITestSessionEventsHandler eventsHandler)
{
return await StopTestSessionAsync(
testSessionInfo,
options: null,
eventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
[Obsolete("This API is not final yet and is subject to changes.", false)]
public async Task<bool> StopTestSessionAsync(
TestSessionInfo? testSessionInfo,
TestPlatformOptions? options,
ITestSessionEventsHandler eventsHandler)
{
_testPlatformEventSource.TranslationLayerStopTestSessionStart();
await EnsureInitializedAsync().ConfigureAwait(false);
return await _requestSender.StopTestSessionAsync(
testSessionInfo,
options,
eventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task InitializeExtensionsAsync(IEnumerable<string> pathToAdditionalExtensions)
{
await EnsureInitializedAsync().ConfigureAwait(false);
_pathToAdditionalExtensions = pathToAdditionalExtensions.ToList();
_requestSender.InitializeExtensions(_pathToAdditionalExtensions);
}
/// <inheritdoc/>
public async Task DiscoverTestsAsync(
IEnumerable<string> sources,
string? discoverySettings,
ITestDiscoveryEventsHandler discoveryEventsHandler)
{
await DiscoverTestsAsync(
sources,
discoverySettings,
options: null,
discoveryEventsHandler: new DiscoveryEventsHandleConverter(discoveryEventsHandler))
.ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task DiscoverTestsAsync(
IEnumerable<string> sources,
string? discoverySettings,
TestPlatformOptions? options,
ITestDiscoveryEventsHandler2 discoveryEventsHandler)
{
await DiscoverTestsAsync(
sources,
discoverySettings,
options,
testSessionInfo: null,
discoveryEventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task DiscoverTestsAsync(
IEnumerable<string> sources,
string? discoverySettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestDiscoveryEventsHandler2 discoveryEventsHandler)
{
_testPlatformEventSource.TranslationLayerDiscoveryStart();
await EnsureInitializedAsync().ConfigureAwait(false);
await _requestSender.DiscoverTestsAsync(
sources,
discoverySettings,
options,
testSessionInfo,
discoveryEventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsAsync(
IEnumerable<string> sources,
string? runSettings,
ITestRunEventsHandler testRunEventsHandler)
{
await RunTestsAsync(
sources,
runSettings,
options: null,
testRunEventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsAsync(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
ITestRunEventsHandler testRunEventsHandler)
{
await RunTestsAsync(
sources,
runSettings,
options,
testSessionInfo: null,
testRunEventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsAsync(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler)
{
await RunTestsAsync(
sources,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
new NoOpTelemetryEventsHandler()).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsAsync(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITelemetryEventsHandler telemetryEventsHandler)
{
var sourceList = sources.ToList();
_testPlatformEventSource.TranslationLayerExecutionStart(
0,
sourceList.Count,
0,
runSettings ?? string.Empty);
await EnsureInitializedAsync().ConfigureAwait(false);
await _requestSender.StartTestRunAsync(
sourceList,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
telemetryEventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsAsync(
IEnumerable<TestCase> testCases,
string? runSettings,
ITestRunEventsHandler testRunEventsHandler)
{
await RunTestsAsync(
testCases,
runSettings,
options: null,
testRunEventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsAsync(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
ITestRunEventsHandler testRunEventsHandler)
{
await RunTestsAsync(
testCases,
runSettings,
options,
testSessionInfo: null,
testRunEventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsAsync(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler)
{
await RunTestsAsync(
testCases,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
new NoOpTelemetryEventsHandler()).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsAsync(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITelemetryEventsHandler telemetryEventsHandler)
{
var testCaseList = testCases.ToList();
_testPlatformEventSource.TranslationLayerExecutionStart(
0,
0,
testCaseList.Count,
runSettings ?? string.Empty);
await EnsureInitializedAsync().ConfigureAwait(false);
await _requestSender.StartTestRunAsync(
testCaseList,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
telemetryEventsHandler).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsWithCustomTestHostAsync(
IEnumerable<string> sources,
string? runSettings,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
await RunTestsWithCustomTestHostAsync(
sources,
runSettings,
options: null,
testRunEventsHandler,
customTestHostLauncher).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsWithCustomTestHostAsync(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
await RunTestsWithCustomTestHostAsync(
sources,
runSettings,
options,
testSessionInfo: null,
testRunEventsHandler,
customTestHostLauncher).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsWithCustomTestHostAsync(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
await RunTestsWithCustomTestHostAsync(
sources,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
new NoOpTelemetryEventsHandler(),
customTestHostLauncher).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsWithCustomTestHostAsync(
IEnumerable<string> sources,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITelemetryEventsHandler telemetryEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
var sourceList = sources.ToList();
_testPlatformEventSource.TranslationLayerExecutionStart(
1,
sourceList.Count,
0,
runSettings ?? string.Empty);
await EnsureInitializedAsync().ConfigureAwait(false);
await _requestSender.StartTestRunWithCustomHostAsync(
sourceList,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
telemetryEventsHandler,
customTestHostLauncher).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsWithCustomTestHostAsync(
IEnumerable<TestCase> testCases,
string? runSettings,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
await RunTestsWithCustomTestHostAsync(
testCases,
runSettings,
options: null,
testRunEventsHandler,
customTestHostLauncher).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsWithCustomTestHostAsync(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
await RunTestsWithCustomTestHostAsync(
testCases,
runSettings,
options,
testSessionInfo: null,
testRunEventsHandler,
customTestHostLauncher).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsWithCustomTestHostAsync(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
await RunTestsWithCustomTestHostAsync(
testCases,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
new NoOpTelemetryEventsHandler(),
customTestHostLauncher).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task RunTestsWithCustomTestHostAsync(
IEnumerable<TestCase> testCases,
string? runSettings,
TestPlatformOptions? options,
TestSessionInfo? testSessionInfo,
ITestRunEventsHandler testRunEventsHandler,
ITelemetryEventsHandler telemetryEventsHandler,
ITestHostLauncher customTestHostLauncher)
{
var testCaseList = testCases.ToList();
_testPlatformEventSource.TranslationLayerExecutionStart(
1,
0,
testCaseList.Count,
runSettings ?? string.Empty);
await EnsureInitializedAsync().ConfigureAwait(false);
await _requestSender.StartTestRunWithCustomHostAsync(
testCaseList,
runSettings,
options,
testSessionInfo,
testRunEventsHandler,
telemetryEventsHandler,
customTestHostLauncher).ConfigureAwait(false);
}
/// <inheritdoc/>
public async Task ProcessTestRunAttachmentsAsync(
IEnumerable<AttachmentSet> attachments,
IEnumerable<InvokedDataCollector>? invokedDataCollectors,
string? processingSettings,
bool isLastBatch,
bool collectMetrics,
ITestRunAttachmentsProcessingEventsHandler testSessionEventsHandler,
CancellationToken cancellationToken)
{
_testPlatformEventSource.TranslationLayerTestRunAttachmentsProcessingStart();
await EnsureInitializedAsync().ConfigureAwait(false);
await _requestSender.ProcessTestRunAttachmentsAsync(
attachments,
invokedDataCollectors,
processingSettings,
collectMetrics,
testSessionEventsHandler,
cancellationToken).ConfigureAwait(false);
}
/// <inheritdoc/>
public Task ProcessTestRunAttachmentsAsync(
IEnumerable<AttachmentSet> attachments,
string? processingSettings,
bool isLastBatch,
bool collectMetrics,
ITestRunAttachmentsProcessingEventsHandler testSessionEventsHandler,
CancellationToken cancellationToken)
=> ProcessTestRunAttachmentsAsync(attachments, [], processingSettings, isLastBatch, collectMetrics, testSessionEventsHandler, cancellationToken);
#endregion
private void EnsureInitialized()
{
if (!_vstestConsoleProcessManager.IsProcessInitialized())
{
EqtTrace.Info("VsTestConsoleWrapper.EnsureInitialized: Process is not started.");
StartSession();
_sessionStarted = WaitForConnection();
if (_sessionStarted)
{
EqtTrace.Info("VsTestConsoleWrapper.EnsureInitialized: Send a request to initialize extensions.");
_requestSender.InitializeExtensions(_pathToAdditionalExtensions);
}
}
if (!_sessionStarted && _requestSender != null)
{
EqtTrace.Info("VsTestConsoleWrapper.EnsureInitialized: Process Started.");
_sessionStarted = WaitForConnection();
}
}
private async Task EnsureInitializedAsync()
{
if (!_vstestConsoleProcessManager.IsProcessInitialized())
{
EqtTrace.Info("VsTestConsoleWrapper.EnsureInitializedAsync: Process is not started.");
await StartSessionAsync().ConfigureAwait(false);
EqtTrace.Info("VsTestConsoleWrapper.EnsureInitializedAsync: Send a request to initialize extensions.");
_requestSender.InitializeExtensions(_pathToAdditionalExtensions);
}
}
private bool WaitForConnection()
{
EqtTrace.Info("VsTestConsoleWrapper.WaitForConnection: Waiting for connection to command line runner.");
var timeout = EnvironmentHelper.GetConnectionTimeout();
if (!_requestSender.WaitForRequestHandlerConnection(timeout * 1000))
{
var currentProcessName = _processHelper.GetCurrentProcessFileName();
var childProcessName = _vstestConsoleProcessManager.ProcessName;
var childProcessId = _vstestConsoleProcessManager.ProcessId;
var childProcessExitCode = _vstestConsoleProcessManager.ExitCode;
var childProcessErrorOutput = _vstestConsoleProcessManager.ErrorOutput;
if (childProcessId == null)
{
// Process failed to start, likely due to antivirus or other startup issues. Recommend checking machine for issues that may prevent process from starting.
throw new TransationLayerException(
string.Format(
CultureInfo.CurrentCulture,
CommunicationUtilitiesResources.ConnectionTimeoutProcessDidNotStartErrorMessage,
currentProcessName,
CoreUtilitiesConstants.VstestConsoleProcessName,
timeout));
}
else if (childProcessExitCode == null)
{
// Process is still alive but failed to connect within the timeout, likely due to machine slowness. Recommend increasing timeout.
throw new TransationLayerException(
string.Format(
CultureInfo.CurrentCulture,
CommunicationUtilitiesResources.ConnectionTimeoutWithDetailsErrorMessage,
currentProcessName,
CoreUtilitiesConstants.VstestConsoleProcessName,
timeout,
childProcessId,
childProcessName,
EnvironmentHelper.VstestConnectionTimeout));
}
else
{
// Process started and exited within the timeout, likely due to startup issues or incompatible environment. Recommend checking the error output for more details.
throw new TransationLayerException(
string.Format(
CultureInfo.CurrentCulture,
CommunicationUtilitiesResources.ConnectionTimeoutProcessExitedErrorMessage,
currentProcessName,
CoreUtilitiesConstants.VstestConsoleProcessName,
timeout,
childProcessId,
childProcessName,
childProcessExitCode,
childProcessErrorOutput)
);
}
}
_testPlatformEventSource.TranslationLayerInitializeStop();
return true;
}
}
|