From 53dcb81446dbeca067429ab42ca4a56c37e5dd96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Tue, 28 Mar 2023 17:51:36 +0200 Subject: [PATCH 1/6] Forward live output from testhost --- playground/TestPlatform.Playground/Program.cs | 6 ++--- .../Hosting/DefaultTestHostManager.cs | 22 ++++++++++++--- .../Hosting/DotnetTestHostManager.cs | 4 +-- .../Hosting/TestHostManagerCallbacks.cs | 27 +++++++++++++++++-- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/playground/TestPlatform.Playground/Program.cs b/playground/TestPlatform.Playground/Program.cs index 63e8b72cf6..8b1c42f21e 100644 --- a/playground/TestPlatform.Playground/Program.cs +++ b/playground/TestPlatform.Playground/Program.cs @@ -88,7 +88,7 @@ static void Main() """; var sources = new[] { - Path.Combine(playground, "MSTest1", "bin", "Debug", "net472", "MSTest1.dll"), + @"C:\Users\jajares\Downloads\UnitTestProject\bin\Debug\net472\UnitTestProject.dll" //Path.Combine(playground, "MSTest2", "bin", "Debug", "net472", "MSTest2.dll"), //Path.Combine(playground, "MSTest1", "bin", "Debug", "net5.0", "MSTest1.dll"), }; @@ -124,7 +124,7 @@ static void Main() var consoleOptions = new ConsoleParameters { EnvironmentVariables = EnvironmentVariables.Variables, - LogFilePath = Path.Combine(here, "logs", "log.txt"), + // LogFilePath = Path.Combine(here, "logs", "log.txt"), TraceLevel = TraceLevel.Off, }; var options = new TestPlatformOptions @@ -154,7 +154,7 @@ static void Main() //r.RunTests(sources, sourceSettings, options, sessionHandler.TestSessionInfo, new TestRunHandler(detailedOutput)); var rd = sw.ElapsedMilliseconds; Console.WriteLine($"Discovery: {discoveryDuration} ms, Run: {rd} ms, Total: {discoveryDuration + rd} ms"); - Console.WriteLine($"Settings:\n{sourceSettings}"); + // Console.WriteLine($"Settings:\n{sourceSettings}"); } public class PlaygroundTestDiscoveryHandler : ITestDiscoveryEventsHandler, ITestDiscoveryEventsHandler2 diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs index acaa329dad..8c3bf53b24 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs @@ -65,8 +65,10 @@ public class DefaultTestHostManager : ITestRuntimeProvider2 private ITestHostLauncher? _customTestHostLauncher; private Process? _testHostProcess; private StringBuilder? _testHostProcessStdError; + private StringBuilder? _testHostProcessStdOut; private IMessageLogger? _messageLogger; private bool _hostExitedEventRaised; + private TestHostManagerCallbacks? _testhostManagerCallbacks; /// /// Initializes a new instance of the class. @@ -123,7 +125,8 @@ internal DefaultTestHostManager( private Action ExitCallBack => process => { TPDebug.Assert(_testHostProcessStdError is not null, "LaunchTestHostAsync must have been called before ExitCallBack"); - TestHostManagerCallbacks.ExitCallBack(_processHelper, process, _testHostProcessStdError, OnHostExited); + TPDebug.Assert(_testhostManagerCallbacks is not null, "Initialize must have been called before ExitCallBack"); + _testhostManagerCallbacks.ExitCallBack(_processHelper, process, _testHostProcessStdError, OnHostExited); }; /// @@ -132,7 +135,18 @@ internal DefaultTestHostManager( private Action ErrorReceivedCallback => (process, data) => { TPDebug.Assert(_testHostProcessStdError is not null, "LaunchTestHostAsync must have been called before ErrorReceivedCallback"); - TestHostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, data); + TPDebug.Assert(_testhostManagerCallbacks is not null, "Initialize must have been called before ErrorReceivedCallback"); + _testhostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, data); + }; + + /// + /// Gets callback to read from process error stream + /// + private Action OutputReceivedCallback => (process, data) => + { + TPDebug.Assert(_testHostProcessStdOut is not null, "LaunchTestHostAsync must have been called before OutputReceivedCallback"); + TPDebug.Assert(_testhostManagerCallbacks is not null, "Initialize must have been called before OutputReceivedCallback"); + _testhostManagerCallbacks.StandardOutputReceivedCallback(_testHostProcessStdOut, data); }; /// @@ -357,6 +371,7 @@ public void Initialize(IMessageLogger? logger, string runsettingsXml) var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(runsettingsXml); _messageLogger = logger; + _testhostManagerCallbacks = new TestHostManagerCallbacks(true, logger); _architecture = runConfiguration.TargetPlatform; _targetFramework = runConfiguration.TargetFramework; _testHostProcess = null; @@ -498,6 +513,7 @@ private void OnHostExited(HostProviderEventArgs e) private bool LaunchHost(TestProcessStartInfo testHostStartInfo, CancellationToken cancellationToken) { _testHostProcessStdError = new StringBuilder(0, CoreUtilities.Constants.StandardErrorMaxLength); + _testHostProcessStdOut = new StringBuilder(0, CoreUtilities.Constants.StandardErrorMaxLength); EqtTrace.Verbose("Launching default test Host Process {0} with arguments {1}", testHostStartInfo.FileName, testHostStartInfo.Arguments); // We launch the test host process here if we're on the normal test running workflow. @@ -519,7 +535,7 @@ private bool LaunchHost(TestProcessStartInfo testHostStartInfo, CancellationToke testHostStartInfo.EnvironmentVariables, ErrorReceivedCallback, ExitCallBack, - null) as Process; + OutputReceivedCallback) as Process; } else { diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs index 6f62385591..406ad2332f 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs @@ -160,7 +160,7 @@ private set private Action ExitCallBack => process => { TPDebug.Assert(_testHostProcessStdError is not null, "_testHostProcessStdError is null"); - TestHostManagerCallbacks.ExitCallBack(_processHelper, process, _testHostProcessStdError, OnHostExited); + new TestHostManagerCallbacks(false, null).ExitCallBack(_processHelper, process, _testHostProcessStdError, OnHostExited); }; /// @@ -169,7 +169,7 @@ private set private Action ErrorReceivedCallback => (process, data) => { TPDebug.Assert(_testHostProcessStdError is not null, "_testHostProcessStdError is null"); - TestHostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, data); + new TestHostManagerCallbacks(false, null).ErrorReceivedCallback(_testHostProcessStdError, data); }; /// diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs index 90d2090e66..b36869183a 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs @@ -9,6 +9,7 @@ using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Extensions; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; namespace Microsoft.TestPlatform.TestHostProvider.Hosting; @@ -16,17 +17,39 @@ namespace Microsoft.TestPlatform.TestHostProvider.Hosting; internal class TestHostManagerCallbacks { private const int E_HANDLE = unchecked((int)0x80070006); + private readonly bool _forwardOutput; + private readonly IMessageLogger? _messageLogger; - public static void ErrorReceivedCallback(StringBuilder testHostProcessStdError, string? data) + public TestHostManagerCallbacks(bool forwardOutput, IMessageLogger? logger) + { + _forwardOutput = forwardOutput; + _messageLogger = logger; + } + + public void StandardOutputReceivedCallback(StringBuilder testHostProcessStdOut, string? data) + { + EqtTrace.Verbose("TestHostManagerCallbacks.StandardOutputReceivedCallback Test host standard output line: {0}", data); + testHostProcessStdOut.AppendSafeWithNewLine(data); + if (_forwardOutput && _messageLogger != null && !StringUtils.IsNullOrWhiteSpace(data)) + { + _messageLogger.SendMessage(TestMessageLevel.Warning, data); + } + } + + public void ErrorReceivedCallback(StringBuilder testHostProcessStdError, string? data) { // Log all standard error message because on too much data we ignore starting part. // This is helpful in abnormal failure of testhost. EqtTrace.Warning("TestHostManagerCallbacks.ErrorReceivedCallback Test host standard error line: {0}", data); testHostProcessStdError.AppendSafeWithNewLine(data); + if (_forwardOutput && _messageLogger != null && !StringUtils.IsNullOrWhiteSpace(data)) + { + _messageLogger.SendMessage(TestMessageLevel.Error, data); + } } - public static void ExitCallBack( + public void ExitCallBack( IProcessHelper processHelper, object? process, StringBuilder testHostProcessStdError, From 608f59d3e055813e99990bf4ed6f43e6c994ac10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Thu, 30 Mar 2023 14:37:30 +0200 Subject: [PATCH 2/6] Forward output for .NET Framework testhost. When VSTEST_EXPERIMENTAL_FORWARD_OUTPUT_FEATURE is 1. --- .../DesignMode/DesignModeClient.cs | 9 +++++--- .../Friends.cs | 2 ++ .../Hosting/DefaultTestHostManager.cs | 2 +- .../Hosting/TestHostManagerCallbacks.cs | 15 ++++++++++++- .../DesignMode/DesignModeClientTests.cs | 22 +++++++++++-------- .../Hosting/TestHostManagerCallbacksTests.cs | 18 +++++++-------- 6 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs b/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs index 5b5a21b029..4c1966a0e7 100644 --- a/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs +++ b/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs @@ -25,6 +25,7 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using CommunicationUtilitiesResources = Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Resources.Resources; @@ -55,7 +56,7 @@ public class DesignModeClient : IDesignModeClient /// Initializes a new instance of the class. /// public DesignModeClient() - : this(new SocketCommunicationManager(), JsonDataSerializer.Instance, new PlatformEnvironment()) + : this(new SocketCommunicationManager(), JsonDataSerializer.Instance, new PlatformEnvironment(), new EnvironmentVariableHelper()) { } @@ -71,13 +72,14 @@ public DesignModeClient() /// /// The platform Environment /// - internal DesignModeClient(ICommunicationManager communicationManager, IDataSerializer dataSerializer, IEnvironment platformEnvironment) + internal DesignModeClient(ICommunicationManager communicationManager, IDataSerializer dataSerializer, IEnvironment platformEnvironment, IEnvironmentVariableHelper environmentVariableHelper) { _communicationManager = communicationManager; _dataSerializer = dataSerializer; _platformEnvironment = platformEnvironment; _testSessionMessageLogger = TestSessionMessageLogger.Instance; _testSessionMessageLogger.TestRunMessage += TestRunMessageHandler; + _isForwardingOutput = environmentVariableHelper.GetEnvironmentVariable("VSTEST_EXPERIMENTAL_FORWARD_OUTPUT_FEATURE") == "1"; } /// @@ -446,7 +448,7 @@ public void TestRunMessageHandler(object? sender, TestRunMessageEventArgs e) case TestMessageLevel.Informational: EqtTrace.Info(e.Message); - if (EqtTrace.IsInfoEnabled) + if (_isForwardingOutput || EqtTrace.IsInfoEnabled) SendTestMessage(e.Level, e.Message); break; @@ -653,6 +655,7 @@ void OnError(TestSessionEventsHandler eventsHandler, Exception? ex) #region IDisposable Support private bool _isDisposed; // To detect redundant calls + private bool _isForwardingOutput; protected virtual void Dispose(bool disposing) { diff --git a/src/Microsoft.TestPlatform.CoreUtilities/Friends.cs b/src/Microsoft.TestPlatform.CoreUtilities/Friends.cs index 770eb71ba5..d20fd5f552 100644 --- a/src/Microsoft.TestPlatform.CoreUtilities/Friends.cs +++ b/src/Microsoft.TestPlatform.CoreUtilities/Friends.cs @@ -30,3 +30,5 @@ [assembly: InternalsVisibleTo("datacollector.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("testhost.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] [assembly: InternalsVisibleTo("vstest.ProgrammerTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] +[assembly: InternalsVisibleTo("Microsoft.TestPlatform.Client.UnitTests, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293")] + diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs index 8c3bf53b24..9a70c70970 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs @@ -371,7 +371,7 @@ public void Initialize(IMessageLogger? logger, string runsettingsXml) var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(runsettingsXml); _messageLogger = logger; - _testhostManagerCallbacks = new TestHostManagerCallbacks(true, logger); + _testhostManagerCallbacks = new TestHostManagerCallbacks(_environmentVariableHelper.GetEnvironmentVariable("VSTEST_EXPERIMENTAL_FORWARD_OUTPUT_FEATURE") == "1", logger); _architecture = runConfiguration.TargetPlatform; _targetFramework = runConfiguration.TargetFramework; _testHostProcess = null; diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs index b36869183a..553712dbef 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs @@ -22,6 +22,19 @@ internal class TestHostManagerCallbacks public TestHostManagerCallbacks(bool forwardOutput, IMessageLogger? logger) { + if (forwardOutput) + { + string? but = null; + if (logger == null) + { + but = " But logger is null, so it won't forward any output."; + } + EqtTrace.Verbose($"TestHostManagerCallbacks.ctor: Experimental forwarding output is enabled.{but}"); + } + else + { + EqtTrace.Verbose($"TestHostManagerCallbacks.ctor: Experimental forwarding output is disabled."); + } _forwardOutput = forwardOutput; _messageLogger = logger; } @@ -32,7 +45,7 @@ public void StandardOutputReceivedCallback(StringBuilder testHostProcessStdOut, testHostProcessStdOut.AppendSafeWithNewLine(data); if (_forwardOutput && _messageLogger != null && !StringUtils.IsNullOrWhiteSpace(data)) { - _messageLogger.SendMessage(TestMessageLevel.Warning, data); + _messageLogger.SendMessage(TestMessageLevel.Informational, data); } } diff --git a/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeClientTests.cs b/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeClientTests.cs index ebd79426ab..a33e376c4b 100644 --- a/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeClientTests.cs +++ b/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeClientTests.cs @@ -22,6 +22,7 @@ using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Moq; @@ -40,14 +41,16 @@ public class DesignModeClientTests private readonly DesignModeClient _designModeClient; private readonly int _protocolVersion = 7; private readonly AutoResetEvent _completeEvent; - private readonly Mock _mockPlatformEnvrironment; + private readonly Mock _mockPlatformEnvironment; + private readonly Mock _mockEnvironmentVariableHelper; public DesignModeClientTests() { _mockTestRequestManager = new Mock(); _mockCommunicationManager = new Mock(); - _mockPlatformEnvrironment = new Mock(); - _designModeClient = new DesignModeClient(_mockCommunicationManager.Object, JsonDataSerializer.Instance, _mockPlatformEnvrironment.Object); + _mockPlatformEnvironment = new Mock(); + _mockEnvironmentVariableHelper = new Mock(); + _designModeClient = new DesignModeClient(_mockCommunicationManager.Object, JsonDataSerializer.Instance, _mockPlatformEnvironment.Object, _mockEnvironmentVariableHelper.Object); _completeEvent = new AutoResetEvent(false); } @@ -283,7 +286,7 @@ public void DesignModeClientOnBadConnectionShouldStopServerAndThrowTimeoutExcept [TestMethod] public void DesignModeClientShouldStopCommunicationOnParentProcessExit() { - _mockPlatformEnvrironment.Setup(pe => pe.Exit(It.IsAny())); + _mockPlatformEnvironment.Setup(pe => pe.Exit(It.IsAny())); _designModeClient.HandleParentProcessExit(); _mockCommunicationManager.Verify(cm => cm.StopClient(), Times.Once); @@ -292,7 +295,7 @@ public void DesignModeClientShouldStopCommunicationOnParentProcessExit() [TestMethod] public void DesignModeClientLaunchCustomHostMustReturnIfAckComes() { - var testableDesignModeClient = new TestableDesignModeClient(_mockCommunicationManager.Object, JsonDataSerializer.Instance, _mockPlatformEnvrironment.Object); + var testableDesignModeClient = new TestableDesignModeClient(_mockCommunicationManager.Object, JsonDataSerializer.Instance, _mockPlatformEnvironment.Object, _mockEnvironmentVariableHelper.Object); _mockCommunicationManager.Setup(cm => cm.WaitForServerConnection(It.IsAny())).Returns(true); @@ -312,7 +315,7 @@ public void DesignModeClientLaunchCustomHostMustReturnIfAckComes() [ExpectedException(typeof(TestPlatformException))] public void DesignModeClientLaunchCustomHostMustThrowIfInvalidAckComes() { - var testableDesignModeClient = new TestableDesignModeClient(_mockCommunicationManager.Object, JsonDataSerializer.Instance, _mockPlatformEnvrironment.Object); + var testableDesignModeClient = new TestableDesignModeClient(_mockCommunicationManager.Object, JsonDataSerializer.Instance, _mockPlatformEnvironment.Object, _mockEnvironmentVariableHelper.Object); _mockCommunicationManager.Setup(cm => cm.WaitForServerConnection(It.IsAny())).Returns(true); @@ -331,7 +334,7 @@ public void DesignModeClientLaunchCustomHostMustThrowIfInvalidAckComes() [ExpectedException(typeof(TestPlatformException))] public void DesignModeClientLaunchCustomHostMustThrowIfCancellationOccursBeforeHostLaunch() { - var testableDesignModeClient = new TestableDesignModeClient(_mockCommunicationManager.Object, JsonDataSerializer.Instance, _mockPlatformEnvrironment.Object); + var testableDesignModeClient = new TestableDesignModeClient(_mockCommunicationManager.Object, JsonDataSerializer.Instance, _mockPlatformEnvironment.Object, _mockEnvironmentVariableHelper.Object); var info = new TestProcessStartInfo(); var cancellationTokenSource = new CancellationTokenSource(); @@ -632,8 +635,9 @@ private class TestableDesignModeClient : DesignModeClient internal TestableDesignModeClient( ICommunicationManager communicationManager, IDataSerializer dataSerializer, - IEnvironment platformEnvironment) - : base(communicationManager, dataSerializer, platformEnvironment) + IEnvironment platformEnvironment, + IEnvironmentVariableHelper environmentVariableHelper) + : base(communicationManager, dataSerializer, platformEnvironment, environmentVariableHelper) { } diff --git a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/TestHostManagerCallbacksTests.cs b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/TestHostManagerCallbacksTests.cs index e0949163ff..9cb8180f25 100644 --- a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/TestHostManagerCallbacksTests.cs +++ b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/TestHostManagerCallbacksTests.cs @@ -27,7 +27,7 @@ public TestHostManagerCallbacksTests() public void ErrorReceivedCallbackShouldAppendNoDataOnNullDataReceived() { _testHostProcessStdError.Append("NoDataShouldAppend"); - TestHostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, null); + new TestHostManagerCallbacks(false, null).ErrorReceivedCallback(_testHostProcessStdError, null); Assert.AreEqual("NoDataShouldAppend", _testHostProcessStdError.ToString()); } @@ -36,7 +36,7 @@ public void ErrorReceivedCallbackShouldAppendNoDataOnNullDataReceived() public void ErrorReceivedCallbackShouldAppendNoDataOnEmptyDataReceived() { _testHostProcessStdError.Append("NoDataShouldAppend"); - TestHostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, string.Empty); + new TestHostManagerCallbacks(false, null).ErrorReceivedCallback(_testHostProcessStdError, string.Empty); Assert.AreEqual("NoDataShouldAppend", _testHostProcessStdError.ToString()); } @@ -45,7 +45,7 @@ public void ErrorReceivedCallbackShouldAppendNoDataOnEmptyDataReceived() public void ErrorReceivedCallbackShouldAppendWhiteSpaceString() { _testHostProcessStdError.Append("OldData"); - TestHostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, " "); + new TestHostManagerCallbacks(false, null).ErrorReceivedCallback(_testHostProcessStdError, " "); Assert.AreEqual("OldData " + Environment.NewLine, _testHostProcessStdError.ToString()); } @@ -54,7 +54,7 @@ public void ErrorReceivedCallbackShouldAppendWhiteSpaceString() public void ErrorReceivedCallbackShouldAppendGivenData() { _testHostProcessStdError.Append("NoDataShouldAppend"); - TestHostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, "new data"); + new TestHostManagerCallbacks(false, null).ErrorReceivedCallback(_testHostProcessStdError, "new data"); Assert.AreEqual("NoDataShouldAppendnew data" + Environment.NewLine, _testHostProcessStdError.ToString()); } @@ -64,7 +64,7 @@ public void ErrorReceivedCallbackShouldNotAppendNewDataIfErrorMessageAlreadyReac { _testHostProcessStdError = new StringBuilder(0, 5); _testHostProcessStdError.Append("12345"); - TestHostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, "678"); + new TestHostManagerCallbacks(false, null).ErrorReceivedCallback(_testHostProcessStdError, "678"); Assert.AreEqual("12345", _testHostProcessStdError.ToString()); } @@ -74,7 +74,7 @@ public void ErrorReceivedCallbackShouldAppendSubStringOfDataIfErrorMessageReache { _testHostProcessStdError = new StringBuilder(0, 5); _testHostProcessStdError.Append("1234"); - TestHostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, "5678"); + new TestHostManagerCallbacks(false, null).ErrorReceivedCallback(_testHostProcessStdError, "5678"); Assert.AreEqual("12345", _testHostProcessStdError.ToString()); } @@ -84,7 +84,7 @@ public void ErrorReceivedCallbackShouldAppendEntireStringEvenItReachesToMaxLengt { _testHostProcessStdError = new StringBuilder(0, 5); _testHostProcessStdError.Append("12"); - TestHostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, "3"); + new TestHostManagerCallbacks(false, null).ErrorReceivedCallback(_testHostProcessStdError, "3"); Assert.AreEqual("123" + Environment.NewLine, _testHostProcessStdError.ToString()); } @@ -94,7 +94,7 @@ public void ErrorReceivedCallbackShouldAppendNewLineApproprioritlyWhenReachingMa { _testHostProcessStdError = new StringBuilder(0, 5); _testHostProcessStdError.Append("123"); - TestHostManagerCallbacks.ErrorReceivedCallback(_testHostProcessStdError, "4"); + new TestHostManagerCallbacks(false, null).ErrorReceivedCallback(_testHostProcessStdError, "4"); Assert.AreEqual("1234" + Environment.NewLine.Substring(0, 1), _testHostProcessStdError.ToString()); } @@ -111,7 +111,7 @@ public void ErrorReceivedCallbackShouldNotCrashIfInvalidProcessHandle() throw err; }); - TestHostManagerCallbacks.ExitCallBack(mock.Object, null, new StringBuilder(), + new TestHostManagerCallbacks(false, null).ExitCallBack(mock.Object, null, new StringBuilder(), hostProviderEventArgs => { onHostExitedCalled = true; From 0993c2fff80c8efe42ebe03d8df5affe52f558c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Thu, 30 Mar 2023 14:40:36 +0200 Subject: [PATCH 3/6] revert playground --- playground/TestPlatform.Playground/Program.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/playground/TestPlatform.Playground/Program.cs b/playground/TestPlatform.Playground/Program.cs index 8b1c42f21e..63e8b72cf6 100644 --- a/playground/TestPlatform.Playground/Program.cs +++ b/playground/TestPlatform.Playground/Program.cs @@ -88,7 +88,7 @@ static void Main() """; var sources = new[] { - @"C:\Users\jajares\Downloads\UnitTestProject\bin\Debug\net472\UnitTestProject.dll" + Path.Combine(playground, "MSTest1", "bin", "Debug", "net472", "MSTest1.dll"), //Path.Combine(playground, "MSTest2", "bin", "Debug", "net472", "MSTest2.dll"), //Path.Combine(playground, "MSTest1", "bin", "Debug", "net5.0", "MSTest1.dll"), }; @@ -124,7 +124,7 @@ static void Main() var consoleOptions = new ConsoleParameters { EnvironmentVariables = EnvironmentVariables.Variables, - // LogFilePath = Path.Combine(here, "logs", "log.txt"), + LogFilePath = Path.Combine(here, "logs", "log.txt"), TraceLevel = TraceLevel.Off, }; var options = new TestPlatformOptions @@ -154,7 +154,7 @@ static void Main() //r.RunTests(sources, sourceSettings, options, sessionHandler.TestSessionInfo, new TestRunHandler(detailedOutput)); var rd = sw.ElapsedMilliseconds; Console.WriteLine($"Discovery: {discoveryDuration} ms, Run: {rd} ms, Total: {discoveryDuration + rd} ms"); - // Console.WriteLine($"Settings:\n{sourceSettings}"); + Console.WriteLine($"Settings:\n{sourceSettings}"); } public class PlaygroundTestDiscoveryHandler : ITestDiscoveryEventsHandler, ITestDiscoveryEventsHandler2 From d77b93ebd8beb5c0989d18e774061379642f05e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Thu, 30 Mar 2023 15:08:10 +0200 Subject: [PATCH 4/6] Make exitCallback static again --- .../Hosting/TestHostManagerCallbacks.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs index 553712dbef..6fabc016bc 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/TestHostManagerCallbacks.cs @@ -62,7 +62,7 @@ public void ErrorReceivedCallback(StringBuilder testHostProcessStdError, string? } } - public void ExitCallBack( + public static void ExitCallBack( IProcessHelper processHelper, object? process, StringBuilder testHostProcessStdError, From 1f0acd79fbc5477359e0da17ee26a40a636d077f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Thu, 30 Mar 2023 15:17:33 +0200 Subject: [PATCH 5/6] And another fix for static --- playground/TestPlatform.Playground/Environment.cs | 1 + .../Hosting/TestHostManagerCallbacksTests.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/playground/TestPlatform.Playground/Environment.cs b/playground/TestPlatform.Playground/Environment.cs index d7ba86c869..d5ec27d0cf 100644 --- a/playground/TestPlatform.Playground/Environment.cs +++ b/playground/TestPlatform.Playground/Environment.cs @@ -14,6 +14,7 @@ internal class EnvironmentVariables ["VSTEST_RUNNER_DEBUG_ATTACHVS"] = "0", ["VSTEST_HOST_DEBUG_ATTACHVS"] = "0", ["VSTEST_DATACOLLECTOR_DEBUG_ATTACHVS"] = "0", + ["VSTEST_EXPERIMENTAL_FORWARD_OUTPUT_FEATURE"] = "1" }; } diff --git a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/TestHostManagerCallbacksTests.cs b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/TestHostManagerCallbacksTests.cs index 9cb8180f25..1f433c77bc 100644 --- a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/TestHostManagerCallbacksTests.cs +++ b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/TestHostManagerCallbacksTests.cs @@ -111,7 +111,7 @@ public void ErrorReceivedCallbackShouldNotCrashIfInvalidProcessHandle() throw err; }); - new TestHostManagerCallbacks(false, null).ExitCallBack(mock.Object, null, new StringBuilder(), + TestHostManagerCallbacks.ExitCallBack(mock.Object, null, new StringBuilder(), hostProviderEventArgs => { onHostExitedCalled = true; From 5f794df34de121669e1522ab9e53e3c08ae98f1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Jare=C5=A1?= Date: Thu, 30 Mar 2023 15:29:48 +0200 Subject: [PATCH 6/6] Fix fix --- .../Hosting/DefaultTestHostManager.cs | 2 +- .../Hosting/DotnetTestHostManager.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs index 9a70c70970..b4e35f6474 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs @@ -126,7 +126,7 @@ internal DefaultTestHostManager( { TPDebug.Assert(_testHostProcessStdError is not null, "LaunchTestHostAsync must have been called before ExitCallBack"); TPDebug.Assert(_testhostManagerCallbacks is not null, "Initialize must have been called before ExitCallBack"); - _testhostManagerCallbacks.ExitCallBack(_processHelper, process, _testHostProcessStdError, OnHostExited); + TestHostManagerCallbacks.ExitCallBack(_processHelper, process, _testHostProcessStdError, OnHostExited); }; /// diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs index 406ad2332f..2957410eac 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs @@ -160,7 +160,7 @@ private set private Action ExitCallBack => process => { TPDebug.Assert(_testHostProcessStdError is not null, "_testHostProcessStdError is null"); - new TestHostManagerCallbacks(false, null).ExitCallBack(_processHelper, process, _testHostProcessStdError, OnHostExited); + TestHostManagerCallbacks.ExitCallBack(_processHelper, process, _testHostProcessStdError, OnHostExited); }; ///