From defaf238142a1a1653c0e64d04d3b1a6fa3f77ea Mon Sep 17 00:00:00 2001 From: DineshChirnanchu Date: Thu, 5 Sep 2019 14:40:58 +0530 Subject: [PATCH] comming changes for #958 fix --- .../TestPluginDiscoverer.cs | 17 +++- .../TesthostProtocol/IDiscoveryManager.cs | 2 +- .../TesthostProtocol/IExecutionManager.cs | 4 +- .../Client/InProcessProxyDiscoveryManager.cs | 2 +- .../Client/InProcessProxyexecutionManager.cs | 2 +- .../Discovery/DiscoveryManager.cs | 3 +- .../EventHandlers/TestRequestHandler.cs | 9 ++- .../Execution/ExecutionManager.cs | 9 ++- .../TestExtenstionInitializeEventsHandler.cs | 79 +++++++++++++++++++ .../Interfaces/ITestRunEventsHandler.cs | 16 ++++ .../Processors/RunTestsArgumentProcessor.cs | 2 +- .../InProcessProxyexecutionManagerTests.cs | 2 +- .../EventHandlers/TestRequestHandlerTests.cs | 4 +- .../Execution/ExecutionManagerTests.cs | 2 +- 14 files changed, 136 insertions(+), 17 deletions(-) create mode 100644 src/Microsoft.TestPlatform.CrossPlatEngine/Execution/TestExtenstionInitializeEventsHandler.cs diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs index 8aed93ac90..ce9581b866 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs @@ -7,12 +7,15 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; + using System.Globalization; using System.IO; using System.Linq; using System.Reflection; - + using System.Security.Cryptography.X509Certificates; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; + using Microsoft.VisualStudio.TestPlatform.Common.Logging; using Microsoft.VisualStudio.TestPlatform.ObjectModel; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; @@ -22,6 +25,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework internal class TestPluginDiscoverer { private IFileHelper fileHelper; + private static bool flag = false; /// /// Initializes a new instance of the class. @@ -85,7 +89,6 @@ internal TestPluginDiscoverer(IFileHelper fileHelper) } this.GetTestExtensionsFromFiles(extensionPaths.ToArray(), pluginInfos); - return pluginInfos; } @@ -138,6 +141,16 @@ private void AddKnownExtensions(ref IEnumerable extensionPaths) this.GetTestExtensionsFromAssembly(assembly, pluginInfos); } } + catch (FileLoadException e) + { + if (!flag) { + flag = true; + EqtTrace.Warning("TestPluginDiscoverer: Failed to load extensions from file '{0}'. Skipping test extension scan for this file. Error: {1}", file, e); + string fileLoadErrorMessage = $"TestPluginDiscoverer: Failed to load extensions from file '" + file + "'"; + TestSessionMessageLogger.Instance.SendMessage(TestMessageLevel.Error, fileLoadErrorMessage); + } + EqtTrace.Warning("TestPluginDiscoverer: Failed to load extensions from file '{0}'. Skipping test extension scan for this file. Error: {1}", file, e); + } catch (Exception e) { EqtTrace.Warning("TestPluginDiscoverer: Failed to load extensions from file '{0}'. Skipping test extension scan for this file. Error: {1}", file, e); diff --git a/src/Microsoft.TestPlatform.Common/Interfaces/Engine/TesthostProtocol/IDiscoveryManager.cs b/src/Microsoft.TestPlatform.Common/Interfaces/Engine/TesthostProtocol/IDiscoveryManager.cs index 400a1eb27d..e60787a968 100644 --- a/src/Microsoft.TestPlatform.Common/Interfaces/Engine/TesthostProtocol/IDiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.Common/Interfaces/Engine/TesthostProtocol/IDiscoveryManager.cs @@ -16,7 +16,7 @@ public interface IDiscoveryManager /// Initializes the discovery manager. /// /// The path to additional extensions. - void Initialize(IEnumerable pathToAdditionalExtensions); + void Initialize(IEnumerable pathToAdditionalExtensions, ITestDiscoveryEventsHandler2 eventHandler); /// /// Discovers tests diff --git a/src/Microsoft.TestPlatform.Common/Interfaces/Engine/TesthostProtocol/IExecutionManager.cs b/src/Microsoft.TestPlatform.Common/Interfaces/Engine/TesthostProtocol/IExecutionManager.cs index 2576e5154f..8f76bd9bda 100644 --- a/src/Microsoft.TestPlatform.Common/Interfaces/Engine/TesthostProtocol/IExecutionManager.cs +++ b/src/Microsoft.TestPlatform.Common/Interfaces/Engine/TesthostProtocol/IExecutionManager.cs @@ -9,6 +9,7 @@ namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtoco using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol; + /// /// Orchestrates test execution related functionality for the engine communicating with the test host process. /// @@ -18,7 +19,8 @@ public interface IExecutionManager /// Initializes the execution manager. /// /// The path to additional extensions. - void Initialize(IEnumerable pathToAdditionalExtensions); + /// EventHandler for handling execution events from Engine. + void Initialize(IEnumerable pathToAdditionalExtensions, ITestExtenstionInitializeEventsHandler testExtenstionInitizlizeEventsHandler); /// /// Starts the test run with sources. diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyDiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyDiscoveryManager.cs index 88ebc83041..db1baf2d1a 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyDiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyDiscoveryManager.cs @@ -105,7 +105,7 @@ private void InitializeExtensions(IEnumerable sources) // We don't need to pass list of extension as we are running inside vstest.console and // it will use TestPluginCache of vstest.console - discoveryManager.Initialize(Enumerable.Empty()); + discoveryManager.Initialize(Enumerable.Empty(), null); } } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyexecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyexecutionManager.cs index 97e7d3aacd..5371a5f53b 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyexecutionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/InProcessProxyexecutionManager.cs @@ -144,7 +144,7 @@ private void InitializeExtensions(IEnumerable sources) // We don't need to pass list of extension as we are running inside vstest.console and // it will use TestPluginCache of vstest.console - executionManager.Initialize(Enumerable.Empty()); + executionManager.Initialize(Enumerable.Empty(), null); } } } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs index 0f724688bf..1f9be3f16c 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs @@ -63,8 +63,9 @@ protected DiscoveryManager(IRequestData requestData, ITestPlatformEventSource te /// Initializes the discovery manager. /// /// The path to additional extensions. - public void Initialize(IEnumerable pathToAdditionalExtensions) + public void Initialize(IEnumerable pathToAdditionalExtensions, ITestDiscoveryEventsHandler2 eventHandler) { + this.testDiscoveryEventsHandler = eventHandler; this.testPlatformEventSource.AdapterSearchStart(); if (pathToAdditionalExtensions != null && pathToAdditionalExtensions.Any()) diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs index b6c81e7fc6..bae1529167 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs @@ -11,6 +11,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommunicationUtilities using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.ObjectModel; using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.EventHandlers; + using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; @@ -110,14 +111,12 @@ public void ProcessRequests(ITestHostManagerFactory testHostManagerFactory) this.testHostManagerFactoryReady.Set(); this.sessionCompleted.Wait(); } - /// public void Dispose() { this.communicationEndPoint.Stop(); this.channel?.Dispose(); } - /// public void Close() { @@ -240,10 +239,11 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec { EqtTrace.Info("Discovery Session Initialize."); this.testHostManagerFactoryReady.Wait(); + var discoveryEventsHandler = new TestDiscoveryEventHandler(this); var pathToAdditionalExtensions = this.dataSerializer.DeserializePayload>(message); jobQueue.QueueJob( () => - testHostManagerFactory.GetDiscoveryManager().Initialize(pathToAdditionalExtensions), 0); + testHostManagerFactory.GetDiscoveryManager().Initialize(pathToAdditionalExtensions, discoveryEventsHandler), 0); break; } @@ -265,10 +265,11 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec { EqtTrace.Info("Execution Session Initialize."); this.testHostManagerFactoryReady.Wait(); + var testExtenstionInitializeEventsHandler = new TestExtenstionInitializeEventsHandler(this); var pathToAdditionalExtensions = this.dataSerializer.DeserializePayload>(message); jobQueue.QueueJob( () => - testHostManagerFactory.GetExecutionManager().Initialize(pathToAdditionalExtensions), 0); + testHostManagerFactory.GetExecutionManager().Initialize(pathToAdditionalExtensions, testExtenstionInitializeEventsHandler), 0); break; } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs index 9a94039b62..d6a0829310 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs @@ -8,6 +8,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution using System.Linq; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; + using Microsoft.VisualStudio.TestPlatform.Common.Logging; using Microsoft.VisualStudio.TestPlatform.Common.SettingsProvider; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing; @@ -20,6 +21,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities; /// @@ -56,7 +58,8 @@ protected ExecutionManager(ITestPlatformEventSource testPlatformEventSource, IRe /// Initializes the execution manager. /// /// The path to additional extensions. - public void Initialize(IEnumerable pathToAdditionalExtensions) + /// EventHandler for handling execution events from Engine. + public void Initialize(IEnumerable pathToAdditionalExtensions, ITestExtenstionInitializeEventsHandler testExtenstionInitializeEventsHandler) { this.testPlatformEventSource.AdapterSearchStart(); @@ -66,8 +69,12 @@ public void Initialize(IEnumerable pathToAdditionalExtensions) TestPluginCache.Instance.DefaultExtensionPaths = pathToAdditionalExtensions; } + testExtenstionInitializeEventsHandler?.SubscribetoSessionEvent(); + this.LoadExtensions(); + testExtenstionInitializeEventsHandler?.UnSubscribetoSessionEvent(); + this.testPlatformEventSource.AdapterSearchStop(); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/TestExtenstionInitializeEventsHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/TestExtenstionInitializeEventsHandler.cs new file mode 100644 index 0000000000..4194428a94 --- /dev/null +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/TestExtenstionInitializeEventsHandler.cs @@ -0,0 +1,79 @@ +using Microsoft.VisualStudio.TestPlatform.Common.Logging; +using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; +using Microsoft.VisualStudio.TestPlatform.ObjectModel; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; +using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution +{ + public class TestExtenstionInitializeEventsHandler : ITestExtenstionInitializeEventsHandler + { + private ITestRequestHandler requestHandler; + + private TestSessionMessageLogger testRunHandler; + + /// + /// Initializes a new instance of the class. + /// + /// test request handler + public TestExtenstionInitializeEventsHandler(ITestRequestHandler requestHandler) + { + this.requestHandler = requestHandler; + testRunHandler = TestSessionMessageLogger.Instance; + } + + public void SubscribetoSessionEvent() + { + testRunHandler.TestRunMessage += TestRunHandler_TestRunMessage; + } + + public void UnSubscribetoSessionEvent() + { + testRunHandler.TestRunMessage -= TestRunHandler_TestRunMessage; + } + + private void TestRunHandler_TestRunMessage(object sender, TestRunMessageEventArgs e) + { + HandleLogMessage(e.Level, e.Message); + } + + /// + /// Handles a test run message. + /// + /// The level. + /// The message. + public void HandleLogMessage(TestMessageLevel level, string message) + { + switch ((TestMessageLevel)level) + { + case TestMessageLevel.Informational: + EqtTrace.Info(message); + break; + + case TestMessageLevel.Warning: + EqtTrace.Warning(message); + break; + + case TestMessageLevel.Error: + EqtTrace.Error(message); + break; + + default: + EqtTrace.Info(message); + break; + } + + this.requestHandler.SendLog(level, message); + } + + public void HandleRawMessage(string rawMessage) + { + // No-Op + // TestHost at this point has no functionality where it requires rawmessage + } + + } +} diff --git a/src/Microsoft.TestPlatform.ObjectModel/Client/Interfaces/ITestRunEventsHandler.cs b/src/Microsoft.TestPlatform.ObjectModel/Client/Interfaces/ITestRunEventsHandler.cs index 171da88e2a..12ac3ebda0 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/Client/Interfaces/ITestRunEventsHandler.cs +++ b/src/Microsoft.TestPlatform.ObjectModel/Client/Interfaces/ITestRunEventsHandler.cs @@ -35,6 +35,22 @@ public interface ITestRunEventsHandler : ITestMessageEventHandler int LaunchProcessWithDebuggerAttached(TestProcessStartInfo testProcessStartInfo); } + /// + /// Interface contract for handling test extenstion initialize events during run operation + /// + public interface ITestExtenstionInitializeEventsHandler : ITestMessageEventHandler + { + /// + /// Subscribe to SessionEvent + /// + void SubscribetoSessionEvent(); + + /// + /// UnSubscribe to SessionEvent + /// + void UnSubscribetoSessionEvent(); + } + /// /// Interface for handling generic message events during test discovery or execution /// diff --git a/src/vstest.console/Processors/RunTestsArgumentProcessor.cs b/src/vstest.console/Processors/RunTestsArgumentProcessor.cs index 568f298b35..52e61e067c 100644 --- a/src/vstest.console/Processors/RunTestsArgumentProcessor.cs +++ b/src/vstest.console/Processors/RunTestsArgumentProcessor.cs @@ -244,7 +244,7 @@ private void TestRunRequest_OnRunCompletion(object sender, TestRunCompleteEventA var testsFoundInAnySource = (e.TestRunStatistics == null) ? false : (e.TestRunStatistics.ExecutedTests > 0); // Indicate the user to use testadapterpath command if there are no tests found - if (!testsFoundInAnySource && string.IsNullOrEmpty(CommandLineOptions.Instance.TestAdapterPath) && this.commandLineOptions.TestCaseFilterValue == null) + if (!testsFoundInAnySource && string.IsNullOrEmpty(CommandLineOptions.Instance.TestAdapterPath) && this.commandLineOptions.TestCaseFilterValue == null) { this.output.Warning(false, CommandLineResources.SuggestTestAdapterPathIfNoTestsIsFound); } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs index 47851d21e7..5a59d09934 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs @@ -50,7 +50,7 @@ public void StartTestRunShouldCallInitialize() var testRunCriteria = new TestRunCriteria(new List { "source.dll" }, 10); this.inProcessProxyExecutionManager.StartTestRun(testRunCriteria, null); - this.mockExecutionManager.Verify(o => o.Initialize(Enumerable.Empty()), Times.Once, "StartTestRun should call Initialize if not already initialized"); + this.mockExecutionManager.Verify(o => o.Initialize(Enumerable.Empty(),null), Times.Once, "StartTestRun should call Initialize if not already initialized"); } [TestMethod] diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs index 912aa8ee75..3782e7b4b7 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs @@ -179,7 +179,7 @@ public void ProcessRequestsDiscoveryInitializeShouldSetExtensionPaths() this.SendMessageOnChannel(message); this.jobQueue.Flush(); - this.mockDiscoveryManager.Verify(d => d.Initialize(It.Is>(paths => paths.Any(p => p.Equals("testadapter.dll"))))); + this.mockDiscoveryManager.Verify(d => d.Initialize(It.Is>(paths => paths.Any(p => p.Equals("testadapter.dll"))),null)); this.SendSessionEnd(); } @@ -224,7 +224,7 @@ public void ProcessRequestsExecutionInitializeShouldSetExtensionPaths() this.SendMessageOnChannel(message); this.jobQueue.Flush(); - this.mockExecutionManager.Verify(e => e.Initialize(It.Is>(paths => paths.Any(p => p.Equals("testadapter.dll"))))); + this.mockExecutionManager.Verify(e => e.Initialize(It.Is>(paths => paths.Any(p => p.Equals("testadapter.dll"))),null)); this.SendSessionEnd(); } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs index 6bc96678c4..166715a50f 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs @@ -80,7 +80,7 @@ public void InitializeShouldLoadAndInitializeAllExtension() () => { }); - this.executionManager.Initialize(new List { commonAssemblyLocation }); + this.executionManager.Initialize(new List { commonAssemblyLocation }, null); Assert.IsNotNull(TestPluginCache.Instance.TestExtensions);