diff --git a/TestPlatform.sln b/TestPlatform.sln index 32f9c47ff0..522ff5788c 100644 --- a/TestPlatform.sln +++ b/TestPlatform.sln @@ -931,18 +931,6 @@ Global {62E9D32B-B989-43CF-81A2-B38B3367FCA3}.Release|x64.Build.0 = Release|Any CPU {62E9D32B-B989-43CF-81A2-B38B3367FCA3}.Release|x86.ActiveCfg = Release|Any CPU {62E9D32B-B989-43CF-81A2-B38B3367FCA3}.Release|x86.Build.0 = Release|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Debug|x64.ActiveCfg = Debug|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Debug|x64.Build.0 = Debug|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Debug|x86.ActiveCfg = Debug|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Debug|x86.Build.0 = Debug|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Release|Any CPU.Build.0 = Release|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Release|x64.ActiveCfg = Release|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Release|x64.Build.0 = Release|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Release|x86.ActiveCfg = Release|Any CPU - {4DA57968-F547-4019-8381-03A218B6C385}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1022,7 +1010,6 @@ Global {29270853-90DC-4C39-9621-F47AE40A79B6} = {B27FAFDF-2DBA-4AB0-BA85-FD5F21D359D6} {186069FE-E1E8-4DE1-BEA4-0FF1484D22D1} = {ED0C35EB-7F31-4841-A24F-8EB708FFA959} {62E9D32B-B989-43CF-81A2-B38B3367FCA3} = {B705537C-B82C-4A30-AFA5-6244D9A7DAEB} - {4DA57968-F547-4019-8381-03A218B6C385} = {6CE2F530-582B-4695-A209-41065E103426} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {0541B30C-FF51-4E28-B172-83F5F3934BCD} diff --git a/scripts/build/TestPlatform.Dependencies.props b/scripts/build/TestPlatform.Dependencies.props index 6e6b856636..7809f30909 100644 --- a/scripts/build/TestPlatform.Dependencies.props +++ b/scripts/build/TestPlatform.Dependencies.props @@ -11,7 +11,7 @@ - 17.3.0-dev + 17.4.0-dev diff --git a/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs b/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs index fd52dbb9f2..bae9ccde27 100644 --- a/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs +++ b/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs @@ -81,7 +81,12 @@ internal DesignModeClient(ICommunicationManager communicationManager, IDataSeria /// /// Property exposing the Instance /// - public static IDesignModeClient? Instance { get; private set; } + public static DesignModeClient? Instance { get; private set; } + + /// + /// Gets the test request manager. + /// + public ITestRequestManager? TestRequestManager { get; internal set; } /// /// Initializes DesignMode @@ -103,7 +108,10 @@ public static void Initialize() /// public void ConnectToClientAndProcessRequests(int port, ITestRequestManager testRequestManager) { - EqtTrace.Info("Trying to connect to server on port: {0}", port); + // Used by the in-process vstest.console wrapper. + TestRequestManager = testRequestManager; + + EqtTrace.Info("Trying to connect to server on port : {0}", port); _communicationManager.SetupClientAsync(new IPEndPoint(IPAddress.Loopback, port)); var connectionTimeoutInSecs = EnvironmentHelper.GetConnectionTimeout(); diff --git a/src/Microsoft.TestPlatform.Client/Friends.cs b/src/Microsoft.TestPlatform.Client/Friends.cs index 81da967ae4..e2d40a1025 100644 --- a/src/Microsoft.TestPlatform.Client/Friends.cs +++ b/src/Microsoft.TestPlatform.Client/Friends.cs @@ -5,11 +5,15 @@ #region Product Assemblies +[assembly: InternalsVisibleTo("vstest.console, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("vstest.console.arm64, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] + #endregion #region Test Assemblies [assembly: InternalsVisibleTo("Microsoft.TestPlatform.Client.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("vstest.ProgrammerTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("vstest.console.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] #endregion diff --git a/src/Microsoft.TestPlatform.Client/Microsoft.TestPlatform.Client.csproj b/src/Microsoft.TestPlatform.Client/Microsoft.TestPlatform.Client.csproj index e100e5c959..38f7e83900 100644 --- a/src/Microsoft.TestPlatform.Client/Microsoft.TestPlatform.Client.csproj +++ b/src/Microsoft.TestPlatform.Client/Microsoft.TestPlatform.Client.csproj @@ -54,8 +54,5 @@ - - - diff --git a/src/Microsoft.TestPlatform.Client/PublicAPI/PublicAPI.Shipped.txt b/src/Microsoft.TestPlatform.Client/PublicAPI/PublicAPI.Shipped.txt index 233c10308c..d2cc0363c6 100644 --- a/src/Microsoft.TestPlatform.Client/PublicAPI/PublicAPI.Shipped.txt +++ b/src/Microsoft.TestPlatform.Client/PublicAPI/PublicAPI.Shipped.txt @@ -76,7 +76,7 @@ Microsoft.VisualStudio.TestPlatform.Client.TestRunAttachmentsProcessing.TestRunA Microsoft.VisualStudio.TestPlatform.Client.TestRunAttachmentsProcessing.TestRunAttachmentsProcessingEventsHandler.HandleTestRunAttachmentsProcessingProgress(Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.TestRunAttachmentsProcessingProgressEventArgs! attachmentsProcessingProgressEventArgs) -> void Microsoft.VisualStudio.TestPlatform.Client.TestRunAttachmentsProcessing.TestRunAttachmentsProcessingEventsHandler.TestRunAttachmentsProcessingEventsHandler(Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces.ICommunicationManager! communicationManager) -> void static Microsoft.VisualStudio.TestPlatform.Client.DesignMode.DesignModeClient.Initialize() -> void -static Microsoft.VisualStudio.TestPlatform.Client.DesignMode.DesignModeClient.Instance.get -> Microsoft.VisualStudio.TestPlatform.Client.DesignMode.IDesignModeClient? +static Microsoft.VisualStudio.TestPlatform.Client.DesignMode.DesignModeClient.Instance.get -> Microsoft.VisualStudio.TestPlatform.Client.DesignMode.DesignModeClient? static Microsoft.VisualStudio.TestPlatform.Client.TestPlatformFactory.GetTestPlatform() -> Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.ITestPlatform! virtual Microsoft.VisualStudio.TestPlatform.Client.DesignMode.DesignModeClient.Dispose(bool disposing) -> void virtual Microsoft.VisualStudio.TestPlatform.Client.Execution.TestRunRequest.HandleTestRunStatsChange(Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.TestRunChangedEventArgs? testRunChangedArgs) -> void @@ -87,3 +87,4 @@ Microsoft.VisualStudio.TestPlatform.Client.Execution.TestRunRequest.AttachDebugg Microsoft.VisualStudio.TestPlatform.Client.RequestHelper.ITestRequestManager.RunTests(Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.TestRunRequestPayload! testRunRequestPayLoad, Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces.ITestHostLauncher3? customTestHostLauncher, Microsoft.VisualStudio.TestPlatform.Common.Interfaces.ITestRunEventsRegistrar! testRunEventsRegistrar, Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.ProtocolConfig! protocolConfig) -> void Microsoft.VisualStudio.TestPlatform.Client.RequestHelper.ITestRequestManager.StartTestSession(Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Payloads.StartTestSessionPayload! payload, Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces.ITestHostLauncher3? testHostLauncher, Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.ITestSessionEventsHandler! eventsHandler, Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.ProtocolConfig! protocolConfig) -> void static Microsoft.VisualStudio.TestPlatform.Client.DesignMode.DesignModeTestHostLauncherFactory.GetCustomHostLauncherForTestRun(Microsoft.VisualStudio.TestPlatform.Client.DesignMode.IDesignModeClient! designModeClient, bool debuggingEnabled) -> Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces.ITestHostLauncher3! +Microsoft.VisualStudio.TestPlatform.Client.DesignMode.DesignModeClient.TestRequestManager.get -> Microsoft.VisualStudio.TestPlatform.Client.RequestHelper.ITestRequestManager? diff --git a/src/Microsoft.TestPlatform.Client/TestPlatform.cs b/src/Microsoft.TestPlatform.Client/TestPlatform.cs index bc53ffb859..6e36e73956 100644 --- a/src/Microsoft.TestPlatform.Client/TestPlatform.cs +++ b/src/Microsoft.TestPlatform.Client/TestPlatform.cs @@ -7,6 +7,7 @@ using System.IO; using System.Linq; using System.Reflection; +using System.Reflection.Metadata; using Microsoft.VisualStudio.TestPlatform.Client.Discovery; using Microsoft.VisualStudio.TestPlatform.Client.Execution; @@ -292,6 +293,16 @@ private static void AddExtensionAssembliesFromExtensionDirectory() } string extensionsFolder = Path.Combine(Path.GetDirectoryName(typeof(TestPlatform).GetTypeInfo().Assembly.GetAssemblyLocation()), "Extensions"); + if (!fileHelper.DirectoryExists(extensionsFolder)) + { + // TODO: Since we no-longer run from \vstest.console\vstest.conosle.exe in Playground, the relative + // extensions folder location changed and we need to patch it. This should be a TEMPORARY solution though, we + // should come up with a better way of fixing this. + // NOTE: This is specific to Playground which references vstest.console from a location that doesn't contain + // the Extensions folder. Normal projects shouldn't have this issue. + extensionsFolder = Path.Combine(Path.GetDirectoryName(extensionsFolder), "vstest.console", "Extensions"); + } + if (fileHelper.DirectoryExists(extensionsFolder)) { // Load default runtime providers diff --git a/src/Microsoft.TestPlatform.Client/TestSession/InProcessTestSessionEventsHandler.cs b/src/Microsoft.TestPlatform.Client/TestSession/InProcessTestSessionEventsHandler.cs new file mode 100644 index 0000000000..e4e568407d --- /dev/null +++ b/src/Microsoft.TestPlatform.Client/TestSession/InProcessTestSessionEventsHandler.cs @@ -0,0 +1,45 @@ +// 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 Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; + +namespace Microsoft.VisualStudio.TestPlatform.Client; + +internal class InProcessTestSessionEventsHandler : ITestSessionEventsHandler +{ + private readonly ITestSessionEventsHandler _testSessionEventsHandler; + + public EventHandler? StartTestSessionCompleteEventHandler { get; set; } + + public EventHandler? StopTestSessionCompleteEventHandler { get; set; } + + public InProcessTestSessionEventsHandler(ITestSessionEventsHandler testSessionEventsHandler) + { + _testSessionEventsHandler = testSessionEventsHandler; + } + + public void HandleLogMessage(TestMessageLevel level, string? message) + { + _testSessionEventsHandler.HandleLogMessage(level, message); + } + + public void HandleRawMessage(string rawMessage) + { + _testSessionEventsHandler.HandleRawMessage(rawMessage); + } + + public void HandleStartTestSessionComplete(StartTestSessionCompleteEventArgs? eventArgs) + { + StartTestSessionCompleteEventHandler?.Invoke(this, eventArgs); + _testSessionEventsHandler.HandleStartTestSessionComplete(eventArgs); + } + + public void HandleStopTestSessionComplete(StopTestSessionCompleteEventArgs? eventArgs) + { + StopTestSessionCompleteEventHandler?.Invoke(this, eventArgs); + _testSessionEventsHandler.HandleStopTestSessionComplete(eventArgs); + } +} diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Friends.cs b/src/Microsoft.TestPlatform.CoreUtilities/Friends.cs index c55a499398..2e7af664b1 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Friends.cs +++ b/src/Microsoft.TestPlatform.CoreUtilities/Friends.cs @@ -37,6 +37,7 @@ [assembly: InternalsVisibleTo("Microsoft.TestPlatform.CommunicationUtilities, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.TestPlatform.ObjectModel, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("Microsoft.VisualStudio.TestPlatform.Common, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("Microsoft.VisualStudio.TestPlatform.Client, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("datacollector.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("testhost.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] diff --git a/src/Microsoft.TestPlatform.Execution.Shared/DebuggerBreakpoint.cs b/src/Microsoft.TestPlatform.Execution.Shared/DebuggerBreakpoint.cs index 4f4d7a2eeb..afbb439cb1 100644 --- a/src/Microsoft.TestPlatform.Execution.Shared/DebuggerBreakpoint.cs +++ b/src/Microsoft.TestPlatform.Execution.Shared/DebuggerBreakpoint.cs @@ -4,6 +4,7 @@ using System; using System.Diagnostics; using System.IO; +using System.Reflection; using System.Runtime.InteropServices; using System.Threading.Tasks; @@ -98,10 +99,18 @@ private static bool AttachVs(Process process, int? vsPid) return fromPath; } - var parent = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); + +# if NETCOREAPP + var parent = AppContext.BaseDirectory; +#else + // Don't use current process MainModule here, it resolves to dotnet if you invoke + // dotnet vstest.console.dll, or dotnet testhost.dll. Use the entry assembly instead. + var parent = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location); +#endif while (parent != null) { var path = Path.Combine(parent, @"src\AttachVS\bin\Debug\net472\AttachVS.exe"); + Debug.WriteLine($"Looking for AttachVS in: {path}."); if (File.Exists(path)) { return path; diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs index de807d83f1..3314a32b00 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs @@ -163,17 +163,20 @@ public virtual TestProcessStartInfo GetTestHostProcessStartInfo( string testHostProcessName = GetTestHostName(_architecture, _targetFramework, _processHelper.GetCurrentProcessArchitecture()); - var currentWorkingDirectory = Path.Combine(Path.GetDirectoryName(typeof(DefaultTestHostManager).GetTypeInfo().Assembly.Location)!, "..//"); + var currentWorkingDirectory = Path.GetDirectoryName(typeof(DefaultTestHostManager).GetTypeInfo().Assembly.Location); var argumentsString = " " + connectionInfo.ToCommandLineOptions(); + TPDebug.Assert(currentWorkingDirectory is not null, "Current working directory must not be null."); + // check in current location for testhost exe var testhostProcessPath = Path.Combine(currentWorkingDirectory, testHostProcessName); + var originalTestHostProcessName = testHostProcessName; if (!File.Exists(testhostProcessPath)) { // "TestHost" is the name of the folder which contain Full CLR built testhost package assemblies, in dotnet SDK. - testHostProcessName = Path.Combine("TestHost", testHostProcessName); - testhostProcessPath = Path.Combine(currentWorkingDirectory, testHostProcessName); + testHostProcessName = Path.Combine("TestHost", originalTestHostProcessName); + testhostProcessPath = Path.Combine(currentWorkingDirectory, "..", testHostProcessName); } if (!Shared) @@ -186,11 +189,27 @@ public virtual TestProcessStartInfo GetTestHostProcessStartInfo( EqtTrace.Verbose("DefaultTestHostmanager: Full path of {0} is {1}", testHostProcessName, testhostProcessPath); var launcherPath = testhostProcessPath; - if (!_environment.OperatingSystem.Equals(PlatformOperatingSystem.Windows) && - !_processHelper.GetCurrentProcessFileName()!.EndsWith(DotnetHostHelper.MONOEXENAME, StringComparison.OrdinalIgnoreCase)) + var processName = _processHelper.GetCurrentProcessFileName(); + if (processName is not null) { - launcherPath = _dotnetHostHelper.GetMonoPath(); - argumentsString = testhostProcessPath.AddDoubleQuote() + " " + argumentsString; + if (!_environment.OperatingSystem.Equals(PlatformOperatingSystem.Windows) && + !processName.EndsWith(DotnetHostHelper.MONOEXENAME, StringComparison.OrdinalIgnoreCase)) + { + launcherPath = _dotnetHostHelper.GetMonoPath(); + argumentsString = testhostProcessPath.AddDoubleQuote() + " " + argumentsString; + } + else + { + // Patching the relative path for IDE scenarios. + if (_environment.OperatingSystem.Equals(PlatformOperatingSystem.Windows) + && !(processName.EndsWith("dotnet", StringComparison.OrdinalIgnoreCase) + || processName.EndsWith("dotnet.exe", StringComparison.OrdinalIgnoreCase)) + && !File.Exists(testhostProcessPath)) + { + testhostProcessPath = Path.Combine(currentWorkingDirectory, "..", originalTestHostProcessName); + launcherPath = testhostProcessPath; + } + } } // For IDEs and other scenario, current directory should be the diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Friends.cs b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Friends.cs index a9db03174f..d39b070d6e 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Friends.cs +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/Friends.cs @@ -11,5 +11,9 @@ [assembly: InternalsVisibleTo("TranslationLayer.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("Microsoft.TestPlatform.TestUtilities, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("TestPlatform.Playground, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("vstest.console, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("vstest.console.arm64, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("vstest.console.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] #endregion diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/PublicAPI/PublicAPI.Shipped.txt b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/PublicAPI/PublicAPI.Shipped.txt index 36f6f2d000..3643b74345 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/PublicAPI/PublicAPI.Shipped.txt +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/PublicAPI/PublicAPI.Shipped.txt @@ -103,7 +103,7 @@ Microsoft.TestPlatform.VsTestConsole.TranslationLayer.TestSession.StopTestSessio Microsoft.TestPlatform.VsTestConsole.TranslationLayer.TestSession.StopTestSessionAsync() -> System.Threading.Tasks.Task! Microsoft.TestPlatform.VsTestConsole.TranslationLayer.TestSession.StopTestSessionAsync(Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.ITestSessionEventsHandler! eventsHandler) -> System.Threading.Tasks.Task! Microsoft.TestPlatform.VsTestConsole.TranslationLayer.TestSession.StopTestSessionAsync(Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.TestPlatformOptions? options, Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.ITestSessionEventsHandler! eventsHandler) -> System.Threading.Tasks.Task! -Microsoft.TestPlatform.VsTestConsole.TranslationLayer.TestSession.TestSession(Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.TestSessionInfo! testSessionInfo, Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.ITestSessionEventsHandler! eventsHandler, Microsoft.TestPlatform.VsTestConsole.TranslationLayer.Interfaces.IVsTestConsoleWrapper! consoleWrapper) -> void +Microsoft.TestPlatform.VsTestConsole.TranslationLayer.TestSession.TestSession(Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.TestSessionInfo? testSessionInfo, Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.ITestSessionEventsHandler! eventsHandler, Microsoft.TestPlatform.VsTestConsole.TranslationLayer.Interfaces.IVsTestConsoleWrapper! consoleWrapper) -> void Microsoft.TestPlatform.VsTestConsole.TranslationLayer.TestSession.TestSessionInfo.get -> Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.TestSessionInfo? Microsoft.TestPlatform.VsTestConsole.TranslationLayer.TestSession.~TestSession() -> void Microsoft.TestPlatform.VsTestConsole.TranslationLayer.TransationLayerException diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/TestSession.cs b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/TestSession.cs index aea930c533..0548fd170f 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/TestSession.cs +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/TestSession.cs @@ -37,7 +37,7 @@ public class TestSession : ITestSession /// The session event handler. /// The encapsulated console wrapper. public TestSession( - TestSessionInfo testSessionInfo, + TestSessionInfo? testSessionInfo, ITestSessionEventsHandler eventsHandler, IVsTestConsoleWrapper consoleWrapper) { diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs index c06f0ed90f..3dc94b17d7 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleProcessManager.cs @@ -228,7 +228,7 @@ private void Process_OutputDataReceived(object sender, DataReceivedEventArgs e) } } - private string[] BuildArguments(ConsoleParameters parameters) + internal string[] BuildArguments(ConsoleParameters parameters) { var args = new List { diff --git a/src/vstest.console/CommandLine/Executor.cs b/src/vstest.console/CommandLine/Executor.cs index 2dc4ea0dee..81ea3efce2 100644 --- a/src/vstest.console/CommandLine/Executor.cs +++ b/src/vstest.console/CommandLine/Executor.cs @@ -16,6 +16,7 @@ using Microsoft.VisualStudio.TestPlatform.Common.Utilities; using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing; using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing.Interfaces; +using Microsoft.VisualStudio.TestPlatform.Execution; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; @@ -82,6 +83,9 @@ internal class Executor internal Executor(IOutput output, ITestPlatformEventSource testPlatformEventSource, IProcessHelper processHelper, IEnvironment environment) { + DebuggerBreakpoint.AttachVisualStudioDebugger("VSTEST_RUNNER_DEBUG_ATTACHVS"); + DebuggerBreakpoint.WaitForDebugger("VSTEST_RUNNER_DEBUG"); + Output = output; _testPlatformEventSource = testPlatformEventSource; _showHelp = true; diff --git a/src/vstest.console/Friends.cs b/src/vstest.console/Friends.cs index 9dd880e408..b6267b9aee 100644 --- a/src/vstest.console/Friends.cs +++ b/src/vstest.console/Friends.cs @@ -9,9 +9,11 @@ #region Test Assemblies +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] + [assembly: InternalsVisibleTo("vstest.console.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("vstest.ProgrammerTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("vstest.console.PlatformTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] +[assembly: InternalsVisibleTo("TestPlatform.Playground, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] #endregion diff --git a/src/vstest.console/HandlerToEventsRegistrarAdapter.cs b/src/vstest.console/HandlerToEventsRegistrarAdapter.cs new file mode 100644 index 0000000000..5cda3ba826 --- /dev/null +++ b/src/vstest.console/HandlerToEventsRegistrarAdapter.cs @@ -0,0 +1,88 @@ +// 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 Microsoft.VisualStudio.TestPlatform.Common.Interfaces; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; + +namespace Microsoft.VisualStudio.TestPlatform.CommandLine; + +internal class DiscoveryHandlerToEventsRegistrarAdapter : ITestDiscoveryEventsRegistrar +{ + private readonly ITestDiscoveryEventsHandler2 _handler; + private readonly EventHandler _handleDiscoveredTests; + private readonly EventHandler _handleLogMessage; + private readonly EventHandler _handleDiscoveryComplete; + private readonly EventHandler _handleRawMessage; + + public DiscoveryHandlerToEventsRegistrarAdapter(ITestDiscoveryEventsHandler2 handler) + { + _handler = handler; + _handleDiscoveredTests += (_, e) => _handler.HandleDiscoveredTests(e.DiscoveredTestCases); + _handleLogMessage += (_, e) => _handler.HandleLogMessage(e.Level, e.Message); + _handleDiscoveryComplete += (_, e) => _handler.HandleDiscoveryComplete(e, null); + _handleRawMessage += (_, e) => _handler.HandleRawMessage(e); + } + + public void LogWarning(string message) + { + _handler.HandleLogMessage(TestMessageLevel.Warning, message); + } + + public void RegisterDiscoveryEvents(IDiscoveryRequest discoveryRequest) + { + discoveryRequest.OnDiscoveredTests += _handleDiscoveredTests; + discoveryRequest.OnDiscoveryMessage += _handleLogMessage; + discoveryRequest.OnDiscoveryComplete += _handleDiscoveryComplete; + discoveryRequest.OnRawMessageReceived += _handleRawMessage; + } + + public void UnregisterDiscoveryEvents(IDiscoveryRequest discoveryRequest) + { + discoveryRequest.OnDiscoveredTests -= _handleDiscoveredTests; + discoveryRequest.OnDiscoveryMessage -= _handleLogMessage; + discoveryRequest.OnDiscoveryComplete -= _handleDiscoveryComplete; + discoveryRequest.OnRawMessageReceived -= _handleRawMessage; + } +} + +internal class RunHandlerToEventsRegistrarAdapter : ITestRunEventsRegistrar +{ + private readonly ITestRunEventsHandler _handler; + private readonly EventHandler _handleLogMessage; + private readonly EventHandler _handleRawMessage; + private readonly EventHandler _handleTestRunStatsChange; + private readonly EventHandler _handleTestRunComplete; + + public RunHandlerToEventsRegistrarAdapter(ITestRunEventsHandler handler) + { + _handler = handler; + _handleLogMessage = (_, e) => _handler.HandleLogMessage(e.Level, e.Message); + _handleRawMessage = (_, e) => _handler.HandleRawMessage(e); + _handleTestRunComplete = (_, e) => _handler.HandleTestRunComplete(e, null, null, null); + _handleTestRunStatsChange = (_, e) => _handler.HandleTestRunStatsChange(e); + } + + public void LogWarning(string message) + { + _handler.HandleLogMessage(TestMessageLevel.Warning, message); + } + + public void RegisterTestRunEvents(ITestRunRequest testRunRequest) + { + testRunRequest.TestRunMessage += _handleLogMessage; + testRunRequest.OnRawMessageReceived += _handleRawMessage; + testRunRequest.OnRunStatsChange += _handleTestRunStatsChange; + testRunRequest.OnRunCompletion += _handleTestRunComplete; + } + + public void UnregisterTestRunEvents(ITestRunRequest testRunRequest) + { + testRunRequest.TestRunMessage -= _handleLogMessage; + testRunRequest.OnRawMessageReceived -= _handleRawMessage; + testRunRequest.OnRunStatsChange -= _handleTestRunStatsChange; + testRunRequest.OnRunCompletion -= _handleTestRunComplete; + } +} diff --git a/src/vstest.console/InProcessVsTestConsoleWrapper.cs b/src/vstest.console/InProcessVsTestConsoleWrapper.cs new file mode 100644 index 0000000000..61c511fb4b --- /dev/null +++ b/src/vstest.console/InProcessVsTestConsoleWrapper.cs @@ -0,0 +1,1106 @@ +// 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; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; + +using Microsoft.TestPlatform.VsTestConsole.TranslationLayer; +using Microsoft.TestPlatform.VsTestConsole.TranslationLayer.Interfaces; +using Microsoft.VisualStudio.TestPlatform.Client; +using Microsoft.VisualStudio.TestPlatform.Client.DesignMode; +using Microsoft.VisualStudio.TestPlatform.Client.RequestHelper; +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.ObjectModel.Client.Payloads; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; +using Microsoft.VisualStudio.TestPlatform.Utilities; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; +using Microsoft.VisualStudio.TestPlatform.VsTestConsole.TranslationLayer.Interfaces; + +namespace Microsoft.VisualStudio.TestPlatform.CommandLine; + +/// +/// The in-process wrapper. +/// +internal class InProcessVsTestConsoleWrapper : IVsTestConsoleWrapper +{ + // Must be in sync with the highest supported version in + // src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs file. + private readonly int _highestSupportedVersion = 6; + + private readonly ITranslationLayerRequestSender _requestSender; + private readonly ITestPlatformEventSource _testPlatformEventSource; + private readonly IEnvironmentVariableHelper _environmentVariableHelper; + + /// + /// Creates a new instance of . + /// + /// + /// The console parameters. + public InProcessVsTestConsoleWrapper(ConsoleParameters consoleParameters) + : this( + consoleParameters, + environmentVariableHelper: new EnvironmentVariableHelper(), + requestSender: new VsTestConsoleRequestSender(), + testRequestManager: null, + executor: new Executor(ConsoleOutput.Instance), + testPlatformEventSource: TestPlatformEventSource.Instance) + { } + + internal InProcessVsTestConsoleWrapper( + ConsoleParameters consoleParameters, + IEnvironmentVariableHelper environmentVariableHelper, + ITranslationLayerRequestSender requestSender, + ITestRequestManager? testRequestManager, + Executor executor, + ITestPlatformEventSource testPlatformEventSource) + { + EqtTrace.Info("VsTestConsoleWrapper.StartSession: Starting VsTestConsoleWrapper session."); + + _environmentVariableHelper = environmentVariableHelper; + _testPlatformEventSource = testPlatformEventSource; + _testPlatformEventSource.TranslationLayerInitializeStart(); + + // Start communication. + _requestSender = requestSender; + var port = _requestSender.InitializeCommunication(); + if (port <= 0) + { + // Close the sender as it failed to host server. + _requestSender.Close(); + throw new TransationLayerException("Error hosting communication channel."); + } + + // Fill the parameters. + consoleParameters.ParentProcessId = Process.GetCurrentProcess().Id; + consoleParameters.PortNumber = port; + + // Start vstest.console. + // TODO: under VS we use consoleParameters.InheritEnvironmentVariables, we take that + // into account when starting a testhost, or clean up in the service host, and use the + // desired set, so all children can inherit it. + foreach (var pair in consoleParameters.EnvironmentVariables) + { + if (pair.Value is null) + { + continue; + } + + _environmentVariableHelper.SetEnvironmentVariable(pair.Key, pair.Value); + } + + string someExistingFile = typeof(InProcessVsTestConsoleWrapper).Assembly.Location; + var args = new VsTestConsoleProcessManager(someExistingFile).BuildArguments(consoleParameters); + // Skip vstest.console path, we are already running in process, so it would just end up + // being understood as test dll to run. (it is present even though we don't provide + // dotnet path, because it is a .dll file). + args = args.Skip(1).ToArray(); + + // We standup the client, and it will allocate port as normal that we will never use. + // This is just to avoid "duplicating" all the setup logic that is done in argument + // processors before client processor. It created design mode client, and stores it as + // single instance. + // We connect back to the client but never use that connection, it only serves as + // "await" to make sure the design mode client is already initialized. + Task.Run(() => executor.Execute(args)); + WaitForConnection(); + + // Set the test request manager here. + TestRequestManager = testRequestManager; + if (TestRequestManager is null) + { + TPDebug.Assert( + (DesignModeClient?)DesignModeClient.Instance != null, + "DesignModeClient.Instance is null"); + TestRequestManager = ((DesignModeClient)DesignModeClient.Instance).TestRequestManager; + } + + _testPlatformEventSource.TranslationLayerInitializeStop(); + } + + internal ITestRequestManager? TestRequestManager { get; set; } + + /// + public void AbortTestRun() + { + try + { + TestRequestManager?.AbortTestRun(); + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.AbortTestRun: Exception occurred: " + ex); + } + } + + /// + public void CancelDiscovery() + { + try + { + TestRequestManager?.CancelDiscovery(); + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.CancelDiscovery: Exception occurred: " + ex); + } + } + + /// + public void CancelTestRun() + { + try + { + TestRequestManager?.CancelTestRun(); + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.CancelTestRun: Exception occurred: " + ex); + } + } + + /// + public void EndSession() + { + // Session means vstest.console process in the original api + // we don't have a process to manage, we are in-process. + } + + /// + public void StartSession() + { + // Session means vstest.console process in the original api + // we don't have a process to manage, we are in-process. + } + + /// + [Obsolete("This API is not final yet and is subject to changes.", false)] + public ITestSession? StartTestSession( + IList sources, + string? runSettings, + ITestSessionEventsHandler eventsHandler) + { + return StartTestSession(sources, runSettings, options: null, eventsHandler); + } + + /// + [Obsolete("This API is not final yet and is subject to changes.", false)] + public ITestSession? StartTestSession( + IList sources, + string? runSettings, + TestPlatformOptions? options, + ITestSessionEventsHandler eventsHandler) + { + return StartTestSession( + sources, + runSettings, + options, + eventsHandler, + testHostLauncher: null); + } + + /// + [Obsolete("This API is not final yet and is subject to changes.", false)] + public ITestSession? StartTestSession( + IList sources, + string? runSettings, + TestPlatformOptions? options, + ITestSessionEventsHandler eventsHandler, + ITestHostLauncher? testHostLauncher) + { + _testPlatformEventSource.TranslationLayerStartTestSessionStart(); + + var resetEvent = new ManualResetEvent(false); + TestSessionInfo? testSessionInfo = null; + + try + { + TestRequestManager?.ResetOptions(); + var startTestSessionPayload = new StartTestSessionPayload() + { + Sources = sources, + RunSettings = runSettings, + HasCustomHostLauncher = testHostLauncher != null, + IsDebuggingEnabled = testHostLauncher != null + && testHostLauncher.IsDebug, + TestPlatformOptions = options + }; + + var inProcessEventsHandler = new InProcessTestSessionEventsHandler(eventsHandler); + inProcessEventsHandler.StartTestSessionCompleteEventHandler += (_, eventArgs) => + { + testSessionInfo = eventArgs?.TestSessionInfo; + resetEvent.Set(); + }; + + TestRequestManager?.StartTestSession( + startTestSessionPayload, + (ITestHostLauncher3?)testHostLauncher, + inProcessEventsHandler, + new ProtocolConfig { Version = _highestSupportedVersion }); + + var timeout = EnvironmentHelper.GetConnectionTimeout() * 1000; + if (!resetEvent.WaitOne(timeout)) + { + throw new TransationLayerException( + string.Format( + CultureInfo.CurrentCulture, + Resources.Resources.StartTestSessionTimedOut, + timeout)); + } + + inProcessEventsHandler.StartTestSessionCompleteEventHandler = null; + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.StartTestSession: Exception occurred: " + ex); + + eventsHandler.HandleLogMessage(TestMessageLevel.Error, ex.ToString()); + eventsHandler.HandleStartTestSessionComplete(new()); + } + + _testPlatformEventSource.TranslationLayerStartTestSessionStop(); + + return new TestSession(testSessionInfo, eventsHandler, this); + } + + /// + [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); + } + + /// + [Obsolete("This API is not final yet and is subject to changes.", false)] + public bool StopTestSession( + TestSessionInfo? testSessionInfo, + TestPlatformOptions? options, + ITestSessionEventsHandler eventsHandler) + { + _testPlatformEventSource.TranslationLayerStopTestSessionStart(); + + var isStopped = false; + var resetEvent = new ManualResetEvent(false); + + try + { + TestRequestManager?.ResetOptions(); + var stopTestSessionPayload = new StopTestSessionPayload() + { + TestSessionInfo = testSessionInfo, + CollectMetrics = options?.CollectMetrics ?? false + }; + + var inProcessEventsHandler = new InProcessTestSessionEventsHandler(eventsHandler); + inProcessEventsHandler.StopTestSessionCompleteEventHandler += (_, eventArgs) => + { + isStopped = (eventArgs?.IsStopped == true); + resetEvent.Set(); + }; + + TestRequestManager?.StopTestSession( + stopTestSessionPayload, + inProcessEventsHandler, + new ProtocolConfig { Version = _highestSupportedVersion }); + + var timeout = EnvironmentHelper.GetConnectionTimeout() * 1000; + if (!resetEvent.WaitOne(timeout)) + { + throw new TransationLayerException( + string.Format( + CultureInfo.CurrentCulture, + Resources.Resources.StopTestSessionTimedOut, + timeout)); + } + + inProcessEventsHandler.StopTestSessionCompleteEventHandler = null; + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.StopTestSession: Exception occurred: " + ex); + + eventsHandler.HandleLogMessage(TestMessageLevel.Error, ex.ToString()); + eventsHandler.HandleStopTestSessionComplete(new()); + } + + _testPlatformEventSource.TranslationLayerStopTestSessionStop(); + + return isStopped; + } + + /// + public void InitializeExtensions(IEnumerable pathToAdditionalExtensions) + { + try + { + TestRequestManager?.InitializeExtensions( + pathToAdditionalExtensions, + skipExtensionFilters: true); + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.InitializeExtensions: Exception occurred: " + ex); + } + } + + /// + public void DiscoverTests( + IEnumerable sources, + string? discoverySettings, + ITestDiscoveryEventsHandler discoveryEventsHandler) + { + DiscoverTests( + sources, + discoverySettings, + options: null, + new DiscoveryEventsHandleConverter(discoveryEventsHandler)); + } + + /// + public void DiscoverTests( + IEnumerable sources, + string? discoverySettings, + TestPlatformOptions? options, + ITestDiscoveryEventsHandler2 discoveryEventsHandler) + { + DiscoverTests( + sources, + discoverySettings, + options, + testSessionInfo: null, + discoveryEventsHandler); + } + + /// + public void DiscoverTests( + IEnumerable sources, + string? discoverySettings, + TestPlatformOptions? options, + TestSessionInfo? testSessionInfo, + ITestDiscoveryEventsHandler2 discoveryEventsHandler) + { + _testPlatformEventSource.TranslationLayerDiscoveryStart(); + + try + { + TestRequestManager?.ResetOptions(); + var discoveryRequestPayload = new DiscoveryRequestPayload() + { + Sources = sources, + RunSettings = discoverySettings, + TestPlatformOptions = options, + TestSessionInfo = testSessionInfo + }; + + TestRequestManager?.DiscoverTests( + discoveryRequestPayload, + new DiscoveryHandlerToEventsRegistrarAdapter(discoveryEventsHandler), + new ProtocolConfig { Version = _highestSupportedVersion }); + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.DiscoverTests: Exception occurred: " + ex); + + discoveryEventsHandler.HandleLogMessage(TestMessageLevel.Error, ex.ToString()); + var errorDiscoveryComplete = new DiscoveryCompleteEventArgs + { + IsAborted = true, + TotalCount = -1, + }; + discoveryEventsHandler.HandleDiscoveryComplete( + errorDiscoveryComplete, + lastChunk: null); + } + + _testPlatformEventSource.TranslationLayerDiscoveryStop(); + } + + /// + public void RunTests( + IEnumerable sources, + string? runSettings, + ITestRunEventsHandler testRunEventsHandler) + { + RunTests( + sources, + runSettings, + options: null, + testRunEventsHandler); + } + + /// + public void RunTests( + IEnumerable sources, + string? runSettings, + TestPlatformOptions? options, + ITestRunEventsHandler testRunEventsHandler) + { + RunTests( + sources, + runSettings, + options, + testSessionInfo: null, + testRunEventsHandler); + } + + /// + public void RunTests( + IEnumerable sources, + string? runSettings, + TestPlatformOptions? options, + TestSessionInfo? testSessionInfo, + ITestRunEventsHandler testRunEventsHandler) + { + var sourceList = sources.ToList(); + _testPlatformEventSource.TranslationLayerExecutionStart( + 0, + 0, + sourceList.Count, + runSettings ?? string.Empty); + + try + { + TestRequestManager?.ResetOptions(); + + var testRunPayload = new TestRunRequestPayload + { + Sources = sourceList.ToList(), + RunSettings = runSettings, + TestPlatformOptions = options, + TestSessionInfo = testSessionInfo + }; + + TestRequestManager?.RunTests( + testRunPayload, + customTestHostLauncher: null, + new RunHandlerToEventsRegistrarAdapter(testRunEventsHandler), + new ProtocolConfig { Version = _highestSupportedVersion }); + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.RunTests: Exception occurred: " + ex); + var testRunCompleteArgs = new TestRunCompleteEventArgs(null, false, true, ex, null, null, TimeSpan.MinValue); + + testRunEventsHandler.HandleLogMessage(TestMessageLevel.Error, ex.ToString()); + testRunEventsHandler.HandleTestRunComplete(testRunCompleteArgs, null, null, null); + } + + _testPlatformEventSource.TranslationLayerExecutionStop(); + } + + /// + public void RunTests( + IEnumerable testCases, + string? runSettings, + ITestRunEventsHandler testRunEventsHandler) + { + RunTests( + testCases, + runSettings, + options: null, + testRunEventsHandler); + } + + /// + public void RunTests( + IEnumerable testCases, + string? runSettings, + TestPlatformOptions? options, + ITestRunEventsHandler testRunEventsHandler) + { + RunTests( + testCases, + runSettings, + options, + testSessionInfo: null, + testRunEventsHandler); + } + + /// + public void RunTests( + IEnumerable testCases, + string? runSettings, + TestPlatformOptions? options, + TestSessionInfo? testSessionInfo, + ITestRunEventsHandler testRunEventsHandler) + { + var testCaseList = testCases.ToList(); + _testPlatformEventSource.TranslationLayerExecutionStart( + 0, + 0, + testCaseList.Count, + runSettings ?? string.Empty); + + try + { + TestRequestManager?.ResetOptions(); + + var testRunPayload = new TestRunRequestPayload + { + TestCases = testCaseList, + RunSettings = runSettings, + TestPlatformOptions = options, + TestSessionInfo = testSessionInfo + }; + + TestRequestManager?.RunTests( + testRunPayload, + customTestHostLauncher: null, + new RunHandlerToEventsRegistrarAdapter(testRunEventsHandler), + new ProtocolConfig { Version = _highestSupportedVersion }); + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.RunTests: Exception occurred: " + ex); + var testRunCompleteArgs = new TestRunCompleteEventArgs(null, false, true, ex, null, null, TimeSpan.MinValue); + + testRunEventsHandler.HandleLogMessage(TestMessageLevel.Error, ex.ToString()); + testRunEventsHandler.HandleTestRunComplete(testRunCompleteArgs, null, null, null); + } + + _testPlatformEventSource.TranslationLayerExecutionStop(); + } + + /// + public void RunTestsWithCustomTestHost( + IEnumerable sources, + string? runSettings, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher? customTestHostLauncher) + { + RunTestsWithCustomTestHost( + sources, + runSettings, + options: null, + testRunEventsHandler, + customTestHostLauncher); + } + + /// + public void RunTestsWithCustomTestHost( + IEnumerable sources, + string? runSettings, + TestPlatformOptions? options, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher? customTestHostLauncher) + { + RunTestsWithCustomTestHost( + sources, + runSettings, + options, + testSessionInfo: null, + testRunEventsHandler, + customTestHostLauncher); + } + + /// + public void RunTestsWithCustomTestHost( + IEnumerable sources, + string? runSettings, + TestPlatformOptions? options, + TestSessionInfo? testSessionInfo, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher? customTestHostLauncher) + { + var sourceList = sources.ToList(); + _testPlatformEventSource.TranslationLayerExecutionStart( + 1, + sourceList.Count, + 0, + runSettings ?? string.Empty); + + try + { + TestRequestManager?.ResetOptions(); + + // We must avoid re-launching the test host if the test run payload already + // contains test session info. Test session info being present is an indicative + // of an already running test host spawned by a start test session call. + var customLauncher = + testSessionInfo is null + ? customTestHostLauncher + : null; + + var testRunPayload = new TestRunRequestPayload + { + Sources = sourceList, + RunSettings = runSettings, + DebuggingEnabled = (customLauncher?.IsDebug == true), + TestPlatformOptions = options, + TestSessionInfo = testSessionInfo + }; + + // TODO: this will need to be via an adapter instead. Because we will get a "live" + // implementation rather than our own implementation that we normally have in design + // mode client. It probably will even throw on this cast. + var upcastCustomLauncher = (ITestHostLauncher3?)customLauncher; + + TestRequestManager?.RunTests( + testRunPayload, + upcastCustomLauncher, + new RunHandlerToEventsRegistrarAdapter(testRunEventsHandler), + new ProtocolConfig { Version = _highestSupportedVersion }); + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.RunTestsWithCustomTestHost: Exception occurred: " + ex); + var testRunCompleteArgs = new TestRunCompleteEventArgs(null, false, true, ex, null, null, TimeSpan.MinValue); + + testRunEventsHandler.HandleLogMessage(TestMessageLevel.Error, ex.ToString()); + testRunEventsHandler.HandleTestRunComplete(testRunCompleteArgs, null, null, null); + } + + _testPlatformEventSource.TranslationLayerExecutionStop(); + } + + /// + public void RunTestsWithCustomTestHost( + IEnumerable testCases, + string? runSettings, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher? customTestHostLauncher) + { + RunTestsWithCustomTestHost( + testCases, + runSettings, + options: null, + testRunEventsHandler, + customTestHostLauncher); + } + + /// + public void RunTestsWithCustomTestHost( + IEnumerable testCases, + string? runSettings, + TestPlatformOptions? options, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher? customTestHostLauncher) + { + RunTestsWithCustomTestHost( + testCases, + runSettings, + options, + testSessionInfo: null, + testRunEventsHandler, + customTestHostLauncher); + } + + /// + public void RunTestsWithCustomTestHost( + IEnumerable testCases, + string? runSettings, + TestPlatformOptions? options, + TestSessionInfo? testSessionInfo, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher? customTestHostLauncher) + { + var testCaseList = testCases.ToList(); + _testPlatformEventSource.TranslationLayerExecutionStart( + 1, + 0, + testCaseList.Count, + runSettings ?? string.Empty); + + try + { + TestRequestManager?.ResetOptions(); + + // We must avoid re-launching the test host if the test run payload already + // contains test session info. Test session info being present is an indicative + // of an already running test host spawned by a start test session call. + var customLauncher = + testSessionInfo is null + ? customTestHostLauncher + : null; + + var testRunPayload = new TestRunRequestPayload + { + TestCases = testCaseList, + RunSettings = runSettings, + DebuggingEnabled = customLauncher?.IsDebug == true, + TestPlatformOptions = options, + TestSessionInfo = testSessionInfo + }; + + // TODO: this will need to be via an adapter instead. Because we will get a "live" + // implementation rather than our own implementation that we normally have in design + // mode client. It probably will even throw on this cast. + var upcastCustomLauncher = (ITestHostLauncher3?)customLauncher; + + TestRequestManager?.RunTests( + testRunPayload, + upcastCustomLauncher, + new RunHandlerToEventsRegistrarAdapter(testRunEventsHandler), + new ProtocolConfig { Version = _highestSupportedVersion }); + } + catch (Exception ex) + { + EqtTrace.Error("InProcessVsTestConsoleWrapper.RunTestsWithCustomTestHost: Exception occurred: " + ex); + var testRunCompleteArgs = new TestRunCompleteEventArgs(null, false, true, ex, null, null, TimeSpan.MinValue); + + testRunEventsHandler.HandleLogMessage(TestMessageLevel.Error, ex.ToString()); + testRunEventsHandler.HandleTestRunComplete(testRunCompleteArgs, null, null, null); + } + + _testPlatformEventSource.TranslationLayerExecutionStop(); + } + + #region Async, not implemented + /// + public async Task DiscoverTestsAsync( + IEnumerable sources, + string? discoverySettings, + ITestDiscoveryEventsHandler discoveryEventsHandler) + { + await DiscoverTestsAsync( + sources, + discoverySettings, + options: null, + new DiscoveryEventsHandleConverter(discoveryEventsHandler)) + .ConfigureAwait(false); + } + + /// + public async Task DiscoverTestsAsync( + IEnumerable sources, + string? discoverySettings, + TestPlatformOptions? options, + ITestDiscoveryEventsHandler2 discoveryEventsHandler) + { + await DiscoverTestsAsync( + sources, + discoverySettings, + options, + testSessionInfo: null, + discoveryEventsHandler) + .ConfigureAwait(false); + } + + /// + public Task DiscoverTestsAsync( + IEnumerable sources, + string? discoverySettings, + TestPlatformOptions? options, + TestSessionInfo? testSessionInfo, + ITestDiscoveryEventsHandler2 discoveryEventsHandler) + { + throw new NotImplementedException(); + } + + /// + public Task InitializeExtensionsAsync(IEnumerable pathToAdditionalExtensions) + { + throw new NotImplementedException(); + } + + /// + public async Task ProcessTestRunAttachmentsAsync( + IEnumerable attachments, + string? processingSettings, + bool isLastBatch, + bool collectMetrics, + ITestRunAttachmentsProcessingEventsHandler eventsHandler, + CancellationToken cancellationToken) + { + await ProcessTestRunAttachmentsAsync( + attachments, + invokedDataCollectors: null, + processingSettings, + isLastBatch, + collectMetrics, + eventsHandler, + cancellationToken) + .ConfigureAwait(false); + } + + /// + public Task ProcessTestRunAttachmentsAsync( + IEnumerable attachments, + IEnumerable? invokedDataCollectors, + string? processingSettings, + bool isLastBatch, + bool collectMetrics, + ITestRunAttachmentsProcessingEventsHandler eventsHandler, + CancellationToken cancellationToken) + { + throw new NotImplementedException(); + } + + /// + public async Task RunTestsAsync( + IEnumerable sources, + string? runSettings, + ITestRunEventsHandler testRunEventsHandler) + { + await RunTestsAsync( + sources, + runSettings, + options: null, + testRunEventsHandler) + .ConfigureAwait(false); + } + + /// + public async Task RunTestsAsync( + IEnumerable sources, + string? runSettings, + TestPlatformOptions? options, + ITestRunEventsHandler testRunEventsHandler) + { + await RunTestsAsync( + sources, + runSettings, + options, + testSessionInfo: null, + testRunEventsHandler) + .ConfigureAwait(false); + } + + /// + public Task RunTestsAsync( + IEnumerable sources, + string? runSettings, + TestPlatformOptions? options, + TestSessionInfo? testSessionInfo, + ITestRunEventsHandler testRunEventsHandler) + { + throw new NotImplementedException(); + } + + /// + public async Task RunTestsAsync( + IEnumerable testCases, + string? runSettings, + ITestRunEventsHandler testRunEventsHandler) + { + await RunTestsAsync( + testCases, + runSettings, + options: null, + testRunEventsHandler) + .ConfigureAwait(false); + } + + /// + public async Task RunTestsAsync( + IEnumerable testCases, + string? runSettings, + TestPlatformOptions? options, + ITestRunEventsHandler testRunEventsHandler) + { + await RunTestsAsync( + testCases, + runSettings, + options, + testSessionInfo: null, + testRunEventsHandler) + .ConfigureAwait(false); + } + + /// + public Task RunTestsAsync( + IEnumerable testCases, + string? runSettings, + TestPlatformOptions? options, + TestSessionInfo? testSessionInfo, + ITestRunEventsHandler testRunEventsHandler) + { + throw new NotImplementedException(); + } + + /// + public async Task RunTestsWithCustomTestHostAsync( + IEnumerable sources, + string? runSettings, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher customTestHostLauncher) + { + await RunTestsWithCustomTestHostAsync( + sources, + runSettings, + options: null, + testRunEventsHandler, + customTestHostLauncher) + .ConfigureAwait(false); + } + + /// + public async Task RunTestsWithCustomTestHostAsync( + IEnumerable sources, + string? runSettings, + TestPlatformOptions? options, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher customTestHostLauncher) + { + await RunTestsWithCustomTestHostAsync( + sources, + runSettings, + options, + testSessionInfo: null, + testRunEventsHandler, + customTestHostLauncher) + .ConfigureAwait(false); + } + + /// + public Task RunTestsWithCustomTestHostAsync( + IEnumerable sources, + string? runSettings, + TestPlatformOptions? options, + TestSessionInfo? testSessionInfo, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher customTestHostLauncher) + { + throw new NotImplementedException(); + } + + /// + public async Task RunTestsWithCustomTestHostAsync( + IEnumerable testCases, + string? runSettings, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher customTestHostLauncher) + { + await RunTestsWithCustomTestHostAsync( + testCases, + runSettings, + options: null, + testRunEventsHandler, + customTestHostLauncher) + .ConfigureAwait(false); + } + + /// + public async Task RunTestsWithCustomTestHostAsync( + IEnumerable testCases, + string? runSettings, + TestPlatformOptions? options, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher customTestHostLauncher) + { + await RunTestsWithCustomTestHostAsync( + testCases, + runSettings, + options, + testSessionInfo: null, + testRunEventsHandler, + customTestHostLauncher) + .ConfigureAwait(false); + } + + /// + public Task RunTestsWithCustomTestHostAsync( + IEnumerable testCases, + string? runSettings, + TestPlatformOptions? options, + TestSessionInfo? testSessionInfo, + ITestRunEventsHandler testRunEventsHandler, + ITestHostLauncher customTestHostLauncher) + { + throw new NotImplementedException(); + } + + /// + public Task StartSessionAsync() + { + throw new NotImplementedException(); + } + + /// + [Obsolete("This API is not final yet and is subject to changes.", false)] + public async Task StartTestSessionAsync( + IList sources, + string? runSettings, + ITestSessionEventsHandler eventsHandler) + { + return await StartTestSessionAsync( + sources, + runSettings, + options: null, + eventsHandler) + .ConfigureAwait(false); + } + + /// + [Obsolete("This API is not final yet and is subject to changes.", false)] + public async Task StartTestSessionAsync( + IList sources, + string? runSettings, + TestPlatformOptions? options, + ITestSessionEventsHandler eventsHandler) + { + return await StartTestSessionAsync( + sources, + runSettings, + options, + eventsHandler, + testHostLauncher: null) + .ConfigureAwait(false); + } + + /// + [Obsolete("This API is not final yet and is subject to changes.", false)] + public Task StartTestSessionAsync( + IList sources, + string? runSettings, + TestPlatformOptions? options, + ITestSessionEventsHandler eventsHandler, + ITestHostLauncher? testHostLauncher) + { + throw new NotImplementedException(); + } + + /// + [Obsolete("This API is not final yet and is subject to changes.", false)] + public async Task StopTestSessionAsync( + TestSessionInfo? testSessionInfo, + ITestSessionEventsHandler eventsHandler) + { + return await StopTestSessionAsync( + testSessionInfo, + options: null, + eventsHandler) + .ConfigureAwait(false); + } + + /// + [Obsolete("This API is not final yet and is subject to changes.", false)] + public Task StopTestSessionAsync( + TestSessionInfo? testSessionInfo, + TestPlatformOptions? options, + ITestSessionEventsHandler eventsHandler) + { + throw new NotImplementedException(); + } + #endregion + + private bool WaitForConnection() + { + EqtTrace.Info("InProcessVsTestConsoleWrapper.WaitForConnection: Waiting for connection to command line runner."); + + var timeout = EnvironmentHelper.GetConnectionTimeout() * 1000; + if (!_requestSender.WaitForRequestHandlerConnection(timeout)) + { + throw new TransationLayerException( + string.Format( + CultureInfo.CurrentCulture, + Resources.Resources.RequestHandlerConnectionTimedOut, + timeout)); + } + + _testPlatformEventSource.TranslationLayerInitializeStop(); + return true; + } +} diff --git a/src/vstest.console/Program.cs b/src/vstest.console/Program.cs index c1e8ef62e9..1b667370cf 100644 --- a/src/vstest.console/Program.cs +++ b/src/vstest.console/Program.cs @@ -2,7 +2,6 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using Microsoft.VisualStudio.TestPlatform.Execution; - using Microsoft.VisualStudio.TestPlatform.Utilities; namespace Microsoft.VisualStudio.TestPlatform.CommandLine; @@ -21,8 +20,6 @@ public static class Program internal static int Run(string[]? args, UiLanguageOverride uiLanguageOverride) { - DebuggerBreakpoint.AttachVisualStudioDebugger("VSTEST_RUNNER_DEBUG_ATTACHVS"); - DebuggerBreakpoint.WaitForDebugger("VSTEST_RUNNER_DEBUG"); uiLanguageOverride.SetCultureSpecifiedByUser(); return new Executor(ConsoleOutput.Instance).Execute(args); } diff --git a/src/vstest.console/Resources/Resources.Designer.cs b/src/vstest.console/Resources/Resources.Designer.cs index 62a6bbdeac..02afb24e9c 100644 --- a/src/vstest.console/Resources/Resources.Designer.cs +++ b/src/vstest.console/Resources/Resources.Designer.cs @@ -1232,6 +1232,15 @@ internal static string ProjectPathNotFound { } } + /// + /// Looks up a localized string similar to Waiting for request handler connection timed out after {0} seconds.. + /// + internal static string RequestHandlerConnectionTimedOut { + get { + return ResourceManager.GetString("RequestHandlerConnectionTimedOut", resourceCulture); + } + } + /// /// Looks up a localized string similar to @<file> /// Read response file for more options.. @@ -1417,6 +1426,15 @@ internal static string StartingExecution { } } + /// + /// Looks up a localized string similar to Waiting for start test session timed out after {0} seconds.. + /// + internal static string StartTestSessionTimedOut { + get { + return ResourceManager.GetString("StartTestSessionTimedOut", resourceCulture); + } + } + /// /// Looks up a localized string similar to Standard Error Messages:. /// @@ -1435,6 +1453,15 @@ internal static string StdOutMessagesBanner { } } + /// + /// Looks up a localized string similar to Waiting for stop test session timed out after {0} seconds.. + /// + internal static string StopTestSessionTimedOut { + get { + return ResourceManager.GetString("StopTestSessionTimedOut", resourceCulture); + } + } + /// /// Looks up a localized string similar to {0} {1}. /// diff --git a/src/vstest.console/Resources/Resources.resx b/src/vstest.console/Resources/Resources.resx index 704681214e..c7d6cc801d 100644 --- a/src/vstest.console/Resources/Resources.resx +++ b/src/vstest.console/Resources/Resources.resx @@ -810,4 +810,13 @@ vstest.console.exe is running in emulated mode as {0}. For better performance, please consider using the native runner vstest.console.arm64.exe. + + Waiting for request handler connection timed out after {0} seconds. + + + Waiting for start test session timed out after {0} seconds. + + + Waiting for stop test session timed out after {0} seconds. + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.cs.xlf b/src/vstest.console/Resources/xlf/Resources.cs.xlf index b23f2be03d..fbf06e3fc4 100644 --- a/src/vstest.console/Resources/xlf/Resources.cs.xlf +++ b/src/vstest.console/Resources/xlf/Resources.cs.xlf @@ -1179,6 +1179,21 @@ Nástroj vstest.console.exe je spuštěn v emulovaném režimu jako {0}. Pokud chcete dosáhnout lepšího výkonu, zvažte použití nativního nástroje runner vstest.console.arm64.exe. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.de.xlf b/src/vstest.console/Resources/xlf/Resources.de.xlf index f727aec4d0..a7ceee318a 100644 --- a/src/vstest.console/Resources/xlf/Resources.de.xlf +++ b/src/vstest.console/Resources/xlf/Resources.de.xlf @@ -1179,6 +1179,21 @@ „vstest.console.exe“ wird im emulierten Modus als {0} ausgeführt. Um eine bessere Leistung zu erzielen, erwägen Sie die Verwendung der nativen Ausführung von „vstest.console.arm64.exe“. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.es.xlf b/src/vstest.console/Resources/xlf/Resources.es.xlf index b39c5b5990..a859287628 100644 --- a/src/vstest.console/Resources/xlf/Resources.es.xlf +++ b/src/vstest.console/Resources/xlf/Resources.es.xlf @@ -1182,6 +1182,21 @@ vstest.console.exe se está ejecutando en modo emulado como {0}. Para obtener un mejor rendimiento, considere la posibilidad de usar el ejecutor nativo vstest.console.arm64.exe. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.fr.xlf b/src/vstest.console/Resources/xlf/Resources.fr.xlf index 4dd69bfa71..142988452f 100644 --- a/src/vstest.console/Resources/xlf/Resources.fr.xlf +++ b/src/vstest.console/Resources/xlf/Resources.fr.xlf @@ -1179,6 +1179,21 @@ Comportements actuellement pris en charge : vstest.console.exe s’exécute en mode émulé en tant que {0}. Pour de meilleures performances, utilisez l’exécuteur natif vstest.console.arm64.exe. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.it.xlf b/src/vstest.console/Resources/xlf/Resources.it.xlf index 5c2ca3d490..b960a91316 100644 --- a/src/vstest.console/Resources/xlf/Resources.it.xlf +++ b/src/vstest.console/Resources/xlf/Resources.it.xlf @@ -1179,6 +1179,21 @@ vstest.console.exe è in esecuzione in modalità emulata come {0}. Per prestazioni migliori, è consigliabile usare lo strumento di esecuzione nativo vstest.console.arm64.exe. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.ja.xlf b/src/vstest.console/Resources/xlf/Resources.ja.xlf index 01075f5f2f..8db9d74746 100644 --- a/src/vstest.console/Resources/xlf/Resources.ja.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ja.xlf @@ -1179,6 +1179,21 @@ vstest.console.exe はエミュレート済みモードで {0} として実行されています。パフォーマンスを向上させるに、ネイティブ ランナー vstest.console.arm64.exe の使用を検討してください。 + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.ko.xlf b/src/vstest.console/Resources/xlf/Resources.ko.xlf index 329607ebe8..ab392741ce 100644 --- a/src/vstest.console/Resources/xlf/Resources.ko.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ko.xlf @@ -1179,6 +1179,21 @@ vstest.console.exe가 에뮬레이트 모드에서 {0}(으)로 실행 중입니다. 더 나은 성능을 위해 네이티브 실행기 vstest.console.arm64.exe 사용을 고려하세요. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.pl.xlf b/src/vstest.console/Resources/xlf/Resources.pl.xlf index e784ee2446..6a174f6191 100644 --- a/src/vstest.console/Resources/xlf/Resources.pl.xlf +++ b/src/vstest.console/Resources/xlf/Resources.pl.xlf @@ -1179,6 +1179,21 @@ Program vstest.console.exe działa w trybie emulowanym jako {0}. Aby uzyskać lepszą wydajność, rozważ użycie natywnego modułu uruchamiającego vstest.console.arm64.exe. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf b/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf index 989f45c03b..7a57ba36cb 100644 --- a/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf +++ b/src/vstest.console/Resources/xlf/Resources.pt-BR.xlf @@ -1179,6 +1179,21 @@ Altere o prefixo de nível de diagnóstico do agente de console, como mostrado a vstest.console.exe está sendo executado no modo emulado como {0}. Para obter um melhor desempenho, considere usar o executor nativo vstest.console.arm64.exe. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.ru.xlf b/src/vstest.console/Resources/xlf/Resources.ru.xlf index 407b4b5c32..c09fd33db9 100644 --- a/src/vstest.console/Resources/xlf/Resources.ru.xlf +++ b/src/vstest.console/Resources/xlf/Resources.ru.xlf @@ -1179,6 +1179,21 @@ vstest.console.exe выполняется в режиме эмуляции как {0}. Для повышения производительности рекомендуется использовать собственное средство выполнения тестов vstest.console.arm64.exe. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.tr.xlf b/src/vstest.console/Resources/xlf/Resources.tr.xlf index cd492722d2..368be585b4 100644 --- a/src/vstest.console/Resources/xlf/Resources.tr.xlf +++ b/src/vstest.console/Resources/xlf/Resources.tr.xlf @@ -1179,6 +1179,21 @@ Günlükler için izleme düzeyini aşağıda gösterildiği gibi değiştirin vstest.console.exe, öykünülen modda {0} olarak çalışıyor. Daha iyi performans için vstest.console.arm64.exe yerel çalıştırıcısını kullanmayı deneyin. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.xlf b/src/vstest.console/Resources/xlf/Resources.xlf index 381944d730..7f3363d811 100644 --- a/src/vstest.console/Resources/xlf/Resources.xlf +++ b/src/vstest.console/Resources/xlf/Resources.xlf @@ -973,6 +973,21 @@ Format : TestRunParameters.Parameter(name="<name>", value="<value>") vstest.console.exe is running in emulated mode as {0}. For better performance, please consider using the native runner vstest.console.arm64.exe. + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf b/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf index c91e88ceac..57196c862e 100644 --- a/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf +++ b/src/vstest.console/Resources/xlf/Resources.zh-Hans.xlf @@ -1179,6 +1179,21 @@ vstest.console.exe 正在模拟模式下运行,因为 {0}。为了获得更好的性能,请考虑使用本机运行程序 vstest.console.arm64.exe。 + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf b/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf index 600ddaf7f2..e9e812a527 100644 --- a/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf +++ b/src/vstest.console/Resources/xlf/Resources.zh-Hant.xlf @@ -1179,6 +1179,21 @@ vstest.console.exe 正在模擬模式下以 {0} 方式執行。為了獲得較佳效能,請考慮使用原生執行器 vstest.console.arm64.exe。 + + Waiting for request handler connection timed out after {0} seconds. + Waiting for request handler connection timed out after {0} seconds. + + + + Waiting for start test session timed out after {0} seconds. + Waiting for start test session timed out after {0} seconds. + + + + Waiting for stop test session timed out after {0} seconds. + Waiting for stop test session timed out after {0} seconds. + + \ No newline at end of file diff --git a/src/vstest.console/vstest.console.csproj b/src/vstest.console/vstest.console.csproj index aca26c8837..bffdcead4d 100644 --- a/src/vstest.console/vstest.console.csproj +++ b/src/vstest.console/vstest.console.csproj @@ -48,6 +48,7 @@ true + diff --git a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs index 3ffd03908e..1264c0cad2 100644 --- a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs +++ b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs @@ -83,11 +83,20 @@ public void ConstructorShouldSetX64ProcessForX64Architecture() [TestMethod] public void GetTestHostProcessStartInfoShouldIncludeFileNameFromSubFolderTestHostWhenCurrentProcessIsDotnet() { - string subFoler = "TestHost"; + _mockProcessHelper.Setup(ph => ph.GetCurrentProcessFileName()).Returns("dotnet.exe"); + var startInfo = _testHostManager.GetTestHostProcessStartInfo(Enumerable.Empty(), null, default); + + Assert.IsTrue(startInfo.FileName!.EndsWith(Path.Combine("TestHost", "testhost.exe"))); + } + [TestMethod] + public void GetTestHostProcessStartInfoShouldNotIncludeFileNameFromSubFolderTestHostWhenCurrentProcessIsIde() + { + _mockProcessHelper.Setup(ph => ph.GetCurrentProcessFileName()).Returns("devenv.exe"); var startInfo = _testHostManager.GetTestHostProcessStartInfo(Enumerable.Empty(), null, default); - Assert.IsTrue(startInfo.FileName!.EndsWith(Path.Combine(subFoler, "testhost.exe"))); + Assert.IsFalse(startInfo.FileName!.EndsWith(Path.Combine("TestHost", "testhost.exe"))); + Assert.IsTrue(startInfo.FileName!.EndsWith("testhost.exe")); } [TestMethod] diff --git a/test/TestAssets/performance/Perfy.TestAdapter/Perfy.TestAdapter.csproj b/test/TestAssets/performance/Perfy.TestAdapter/Perfy.TestAdapter.csproj index 77e50b04a4..c1613de05a 100644 --- a/test/TestAssets/performance/Perfy.TestAdapter/Perfy.TestAdapter.csproj +++ b/test/TestAssets/performance/Perfy.TestAdapter/Perfy.TestAdapter.csproj @@ -2,7 +2,7 @@ - net6.0;net48 + net6.0;net48;net472;net471;net5.0 netcoreapp3.1 false false diff --git a/test/TestAssets/performance/Perfy.TestAdapter/Perfy.cs b/test/TestAssets/performance/Perfy.TestAdapter/Perfy.cs index b9b5954954..64ccf1d648 100644 --- a/test/TestAssets/performance/Perfy.TestAdapter/Perfy.cs +++ b/test/TestAssets/performance/Perfy.TestAdapter/Perfy.cs @@ -60,9 +60,13 @@ public void DiscoverTests(IEnumerable _, IDiscoveryContext _2, IMessageLogger _3, ITestCaseDiscoverySink discoverySink) { var location = typeof(Perfy).Assembly.Location; + var tps = new List(); + Func validator = (object o) => !string.IsNullOrWhiteSpace(o as string); + for (var i = 0; i < Count; i++) { - discoverySink.SendTestCase(new TestCase($"Test{i}", Uri, location)); + var tc = new TestCase($"Test{i}", Uri, location); + discoverySink.SendTestCase(tc); } } } diff --git a/test/vstest.console.UnitTests/InProcessVsTestConsoleWrapperTests.cs b/test/vstest.console.UnitTests/InProcessVsTestConsoleWrapperTests.cs new file mode 100644 index 0000000000..c7e534e5cf --- /dev/null +++ b/test/vstest.console.UnitTests/InProcessVsTestConsoleWrapperTests.cs @@ -0,0 +1,852 @@ +// 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; +using System.Linq; + +using Microsoft.TestPlatform.VsTestConsole.TranslationLayer; +using Microsoft.TestPlatform.VsTestConsole.TranslationLayer.Interfaces; +using Microsoft.VisualStudio.TestPlatform.Client; +using Microsoft.VisualStudio.TestPlatform.Client.RequestHelper; +using Microsoft.VisualStudio.TestPlatform.Common.Interfaces; +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.ObjectModel.Client.Payloads; +using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; +using Microsoft.VisualStudio.TestPlatform.Utilities; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +using FluentAssertions; +using Moq; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; + +namespace Microsoft.VisualStudio.TestPlatform.CommandLine.UnitTests; + +[TestClass] +public class InProcessVsTestConsoleWrapperTests +{ + private readonly InProcessVsTestConsoleWrapper _consoleWrapper; + private readonly Mock _mockEnvironmentVariableHelper; + private readonly Mock _mockRequestSender; + private readonly Mock _mockTestRequestManager; + private readonly Mock _mockOutput; + private readonly Executor _executor; + private readonly Mock _mockEventSource; + + private readonly IList _testSources = new List() { "test1", "test2" }; + private readonly IList _testCases = new List() { new TestCase(), new TestCase() }; + private readonly string _runSettings = "dummy runsettings"; + + public InProcessVsTestConsoleWrapperTests() + { + _mockEnvironmentVariableHelper = new Mock(); + + _mockRequestSender = new Mock(); + _mockRequestSender.Setup(rs => rs.InitializeCommunication()).Returns(1234); + _mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + + _mockTestRequestManager = new Mock(); + _mockTestRequestManager.Setup(trm => trm.ResetOptions()).Callback(() => { }); + + _mockOutput = new Mock(); + _executor = new Executor(_mockOutput.Object, new Mock().Object, new ProcessHelper(), new PlatformEnvironment()); + _mockEventSource = new Mock(); + + _consoleWrapper = new InProcessVsTestConsoleWrapper( + new ConsoleParameters(), + _mockEnvironmentVariableHelper.Object, + _mockRequestSender.Object, + _mockTestRequestManager.Object, + _executor, + _mockEventSource.Object); + } + + [TestMethod] + public void InProcessWrapperConstructorShouldThrowIfPortIsInvalid() + { + _mockRequestSender.Setup(rs => rs.InitializeCommunication()).Returns(-1); + + Assert.ThrowsException(() => + new InProcessVsTestConsoleWrapper( + new ConsoleParameters(), + _mockEnvironmentVariableHelper.Object, + _mockRequestSender.Object, + _mockTestRequestManager.Object, + new Executor(_mockOutput.Object, new Mock().Object, new ProcessHelper(), new PlatformEnvironment()), + new Mock().Object)); + } + + [TestMethod] + public void InProcessWrapperConstructorShouldSetEnvironmentVariablesReceivedAsConsoleParameters() + { + const string environmentVariableName = "AAAAA"; + + Environment.GetEnvironmentVariable(environmentVariableName).Should().BeNull(); + + var consoleParams = new ConsoleParameters(); + consoleParams.EnvironmentVariables.Add(environmentVariableName, "1"); + + var _ = new InProcessVsTestConsoleWrapper( + consoleParams, + _mockEnvironmentVariableHelper.Object, + _mockRequestSender.Object, + _mockTestRequestManager.Object, + new Executor(_mockOutput.Object, new Mock().Object, new ProcessHelper(), new PlatformEnvironment()), + new Mock().Object); + + _mockEnvironmentVariableHelper.Verify(evh => evh.SetEnvironmentVariable(environmentVariableName, "1")); + } + + [TestMethod] + public void InProcessWrapperDiscoverTestsWithThreeParamsIsSuccessfullyInvoked() + { + var discoveryEventHandler = new Mock(); + + DiscoveryRequestPayload? payload = null; + _mockTestRequestManager + .Setup(trm => trm.DiscoverTests( + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + DiscoveryRequestPayload p, + ITestDiscoveryEventsRegistrar _, + ProtocolConfig _) => payload = p); + + _consoleWrapper.DiscoverTests(_testSources, _runSettings, discoveryEventHandler.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testSources.SequenceEqual(payload.Sources!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.IsNull(payload.TestPlatformOptions); + Assert.IsNull(payload.TestSessionInfo); + + _mockEventSource.Verify(es => es.TranslationLayerDiscoveryStart(), Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerDiscoveryStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.DiscoverTests( + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperDiscoverTestsWithFourParamsIsSuccessfullyInvoked() + { + var options = new TestPlatformOptions(); + var discoveryEventHandler = new Mock(); + + DiscoveryRequestPayload? payload = null; + _mockTestRequestManager + .Setup(trm => trm.DiscoverTests( + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + DiscoveryRequestPayload p, + ITestDiscoveryEventsRegistrar _, + ProtocolConfig _) => payload = p); + + _consoleWrapper.DiscoverTests(_testSources, _runSettings, options, discoveryEventHandler.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testSources.SequenceEqual(payload.Sources!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.AreEqual(options, payload.TestPlatformOptions); + Assert.IsNull(payload.TestSessionInfo); + + _mockEventSource.Verify(es => es.TranslationLayerDiscoveryStart(), Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerDiscoveryStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.DiscoverTests( + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperDiscoverTestsWithFiveParamsIsSuccessfullyInvoked() + { + var options = new TestPlatformOptions(); + var testSessionInfo = new TestSessionInfo(); + + var discoveryEventHandler = new Mock(); + + DiscoveryRequestPayload? payload = null; + _mockTestRequestManager + .Setup(trm => trm.DiscoverTests( + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + DiscoveryRequestPayload p, + ITestDiscoveryEventsRegistrar _, + ProtocolConfig _) => payload = p); + + _consoleWrapper.DiscoverTests(_testSources, _runSettings, options, testSessionInfo, discoveryEventHandler.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testSources.SequenceEqual(payload.Sources!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.AreEqual(options, payload.TestPlatformOptions); + Assert.AreEqual(testSessionInfo.Id, payload.TestSessionInfo?.Id); + + _mockEventSource.Verify(es => es.TranslationLayerDiscoveryStart(), Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerDiscoveryStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.DiscoverTests( + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithSourcesWithThreeParamsIsSuccessfullyInvoked() + { + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 _, + ITestRunEventsRegistrar _, + ProtocolConfig _) => payload = p); + + _consoleWrapper.RunTests(_testSources, _runSettings, runEventHandler.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testSources.SequenceEqual(payload.Sources!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.IsNull(payload.TestPlatformOptions); + Assert.IsNull(payload.TestSessionInfo?.Id); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 0, + 0, + _testSources.Count, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithSourcesWithFourParamsIsSuccessfullyInvoked() + { + var options = new TestPlatformOptions(); + + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 _, + ITestRunEventsRegistrar _, + ProtocolConfig _) => payload = p); + + _consoleWrapper.RunTests(_testSources, _runSettings, options, runEventHandler.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testSources.SequenceEqual(payload.Sources!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.AreEqual(options, payload.TestPlatformOptions); + Assert.IsNull(payload.TestSessionInfo?.Id); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 0, + 0, + _testSources.Count, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithSourcesWithFiveParamsIsSuccessfullyInvoked() + { + var options = new TestPlatformOptions(); + var testSessionInfo = new TestSessionInfo(); + + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 _, + ITestRunEventsRegistrar _, + ProtocolConfig _) => payload = p); + + _consoleWrapper.RunTests(_testSources, _runSettings, options, testSessionInfo, runEventHandler.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testSources.SequenceEqual(payload.Sources!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.AreEqual(options, payload.TestPlatformOptions); + Assert.AreEqual(testSessionInfo.Id, payload.TestSessionInfo?.Id); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 0, + 0, + _testSources.Count, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithTestsWithThreeParamsIsSuccessfullyInvoked() + { + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 _, + ITestRunEventsRegistrar _, + ProtocolConfig _) => payload = p); + + _consoleWrapper.RunTests(_testCases, _runSettings, runEventHandler.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testCases.SequenceEqual(payload.TestCases!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.IsNull(payload.TestPlatformOptions); + Assert.IsNull(payload.TestSessionInfo?.Id); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 0, + 0, + _testCases.Count, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithTestsWithFourParamsIsSuccessfullyInvoked() + { + var options = new TestPlatformOptions(); + + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 _, + ITestRunEventsRegistrar _, + ProtocolConfig _) => payload = p); + + _consoleWrapper.RunTests(_testCases, _runSettings, options, runEventHandler.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testCases.SequenceEqual(payload.TestCases!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.AreEqual(options, payload.TestPlatformOptions); + Assert.IsNull(payload.TestSessionInfo?.Id); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 0, + 0, + _testCases.Count, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithTestsWithFiveParamsIsSuccessfullyInvoked() + { + var options = new TestPlatformOptions(); + var testSessionInfo = new TestSessionInfo(); + + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 _, + ITestRunEventsRegistrar _, + ProtocolConfig _) => payload = p); + + _consoleWrapper.RunTests(_testCases, _runSettings, options, testSessionInfo, runEventHandler.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testCases.SequenceEqual(payload.TestCases!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.AreEqual(options, payload.TestPlatformOptions); + Assert.AreEqual(testSessionInfo.Id, payload.TestSessionInfo?.Id); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 0, + 0, + _testCases.Count, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithCustomTestHostWithSourcesWithThreeParamsIsSuccessfullyInvoked() + { + var testHostLauncher = new Mock(); + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + ITestHostLauncher3? launcher = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 l, + ITestRunEventsRegistrar _, + ProtocolConfig _) => + { + payload = p; + launcher = l; + }); + + _consoleWrapper.RunTestsWithCustomTestHost(_testSources, _runSettings, runEventHandler.Object, testHostLauncher.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testSources.SequenceEqual(payload.Sources!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.IsNull(payload.TestPlatformOptions); + Assert.IsNull(payload.TestSessionInfo?.Id); + Assert.AreEqual(testHostLauncher.Object.IsDebug, payload.DebuggingEnabled); + Assert.AreEqual(testHostLauncher.Object, launcher); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 1, + _testSources.Count, + 0, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + testHostLauncher.Object, + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithCustomTestHostWithSourcesWithFourParamsIsSuccessfullyInvoked() + { + var options = new TestPlatformOptions(); + + var testHostLauncher = new Mock(); + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + ITestHostLauncher3? launcher = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 l, + ITestRunEventsRegistrar _, + ProtocolConfig _) => + { + payload = p; + launcher = l; + }); + + _consoleWrapper.RunTestsWithCustomTestHost(_testSources, _runSettings, options, runEventHandler.Object, testHostLauncher.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testSources.SequenceEqual(payload.Sources!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.AreEqual(options, payload.TestPlatformOptions); + Assert.IsNull(payload.TestSessionInfo?.Id); + Assert.AreEqual(testHostLauncher.Object.IsDebug, payload.DebuggingEnabled); + Assert.AreEqual(testHostLauncher.Object, launcher); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 1, + _testSources.Count, + 0, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + testHostLauncher.Object, + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithCustomTestHostWithSourcesWithFiveParamsIsSuccessfullyInvoked() + { + var options = new TestPlatformOptions(); + var testSessionInfo = new TestSessionInfo(); + + var testHostLauncher = new Mock(); + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + ITestHostLauncher3? launcher = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 l, + ITestRunEventsRegistrar _, + ProtocolConfig _) => + { + payload = p; + launcher = l; + }); + + _consoleWrapper.RunTestsWithCustomTestHost(_testSources, _runSettings, options, testSessionInfo, runEventHandler.Object, testHostLauncher.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testSources.SequenceEqual(payload.Sources!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.AreEqual(options, payload.TestPlatformOptions); + Assert.AreEqual(testSessionInfo.Id, payload.TestSessionInfo?.Id); + Assert.AreEqual(testHostLauncher.Object.IsDebug, payload.DebuggingEnabled); + Assert.IsNull(launcher); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 1, + _testSources.Count, + 0, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + null, + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithCustomTestHostWithTestsWithThreeParamsIsSuccessfullyInvoked() + { + var testHostLauncher = new Mock(); + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + ITestHostLauncher3? launcher = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 l, + ITestRunEventsRegistrar _, + ProtocolConfig _) => + { + payload = p; + launcher = l; + }); + + _consoleWrapper.RunTestsWithCustomTestHost(_testCases, _runSettings, runEventHandler.Object, testHostLauncher.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testCases.SequenceEqual(payload.TestCases!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.IsNull(payload.TestPlatformOptions); + Assert.IsNull(payload.TestSessionInfo?.Id); + Assert.AreEqual(testHostLauncher.Object.IsDebug, payload.DebuggingEnabled); + Assert.AreEqual(testHostLauncher.Object, launcher); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 1, + 0, + _testCases.Count, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + testHostLauncher.Object, + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithCustomTestHostWithTestsWithFourParamsIsSuccessfullyInvoked() + { + var options = new TestPlatformOptions(); + + var testHostLauncher = new Mock(); + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + ITestHostLauncher3? launcher = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 l, + ITestRunEventsRegistrar _, + ProtocolConfig _) => + { + payload = p; + launcher = l; + }); + + _consoleWrapper.RunTestsWithCustomTestHost(_testCases, _runSettings, options, runEventHandler.Object, testHostLauncher.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testCases.SequenceEqual(payload.TestCases!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.AreEqual(options, payload.TestPlatformOptions); + Assert.IsNull(payload.TestSessionInfo?.Id); + Assert.AreEqual(testHostLauncher.Object.IsDebug, payload.DebuggingEnabled); + Assert.AreEqual(testHostLauncher.Object, launcher); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 1, + 0, + _testCases.Count, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + testHostLauncher.Object, + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + public void InProcessWrapperRunTestsWithCustomTestHostWithTestsWithFiveParamsIsSuccessfullyInvoked() + { + var options = new TestPlatformOptions(); + var testSessionInfo = new TestSessionInfo(); + + var testHostLauncher = new Mock(); + var runEventHandler = new Mock(); + + TestRunRequestPayload? payload = null; + ITestHostLauncher3? launcher = null; + _mockTestRequestManager + .Setup(trm => trm.RunTests( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + TestRunRequestPayload p, + ITestHostLauncher3 l, + ITestRunEventsRegistrar _, + ProtocolConfig _) => + { + payload = p; + launcher = l; + }); + + _consoleWrapper.RunTestsWithCustomTestHost(_testCases, _runSettings, options, testSessionInfo, runEventHandler.Object, testHostLauncher.Object); + + Assert.IsNotNull(payload); + Assert.IsTrue(_testCases.SequenceEqual(payload.TestCases!)); + Assert.AreEqual(_runSettings, payload.RunSettings); + Assert.AreEqual(options, payload.TestPlatformOptions); + Assert.AreEqual(testSessionInfo.Id, payload.TestSessionInfo?.Id); + Assert.AreEqual(testHostLauncher.Object.IsDebug, payload.DebuggingEnabled); + Assert.IsNull(launcher); + + _mockEventSource.Verify(es => + es.TranslationLayerExecutionStart( + 1, + 0, + _testCases.Count, + _runSettings), + Times.Once); + _mockEventSource.Verify(es => es.TranslationLayerExecutionStop(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Once); + _mockTestRequestManager.Verify(trm => trm.RunTests( + It.IsAny(), + null, + It.IsAny(), + It.IsAny()), Times.Once); + } + + [TestMethod] + [Obsolete("Test uses obsolete API")] + public void InProcessWrapperStartTestSessionSucceedsWhenNoExceptionIsThrown() + { + var mockTestSessionEventsHandler = new Mock(); + mockTestSessionEventsHandler + .Setup(eh => eh.HandleStartTestSessionComplete(It.IsAny())) + .Callback(() => { }); + + var testSessionInfo = new TestSessionInfo(); + var startTestSessionCompleteArgs = new StartTestSessionCompleteEventArgs() + { + TestSessionInfo = testSessionInfo + }; + + var stopTestSessionCompleteArgs = new StopTestSessionCompleteEventArgs() + { + IsStopped = true, + TestSessionInfo = testSessionInfo + }; + + _mockTestRequestManager.Setup(trm => + trm.StartTestSession( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + StartTestSessionPayload _, + ITestHostLauncher3 _, + ITestSessionEventsHandler eventsHandler, + ProtocolConfig _) => + eventsHandler.HandleStartTestSessionComplete(startTestSessionCompleteArgs)); + + _mockTestRequestManager.Setup(trm => + trm.StopTestSession( + It.IsAny(), + It.IsAny(), + It.IsAny())) + .Callback(( + StopTestSessionPayload _, + ITestSessionEventsHandler eventsHandler, + ProtocolConfig _) => + eventsHandler.HandleStopTestSessionComplete(stopTestSessionCompleteArgs)); + + var consoleWrapper = new InProcessVsTestConsoleWrapper( + new ConsoleParameters(), + _mockEnvironmentVariableHelper.Object, + _mockRequestSender.Object, + _mockTestRequestManager.Object, + new Executor(_mockOutput.Object, new Mock().Object, new ProcessHelper(), new PlatformEnvironment()), + new Mock().Object); + + using (var testSession = consoleWrapper?.StartTestSession(_testSources, _runSettings, mockTestSessionEventsHandler.Object)) + { + Assert.AreEqual( + testSession?.TestSessionInfo, + testSessionInfo); + } + + _mockTestRequestManager.Verify(trm => trm.ResetOptions(), Times.Exactly(2)); + _mockTestRequestManager.Verify(trm => trm.StartTestSession( + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockTestRequestManager.Verify(trm => trm.StopTestSession( + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + + mockTestSessionEventsHandler.Verify(eh => eh.HandleStartTestSessionComplete(startTestSessionCompleteArgs), Times.Once); + mockTestSessionEventsHandler.Verify(eh => eh.HandleStopTestSessionComplete(stopTestSessionCompleteArgs), Times.Once); + } +}