diff --git a/src/Microsoft.TestPlatform.Common/Constants.cs b/src/Microsoft.TestPlatform.Common/Constants.cs index 93a6988e5a..9f86b7f26b 100644 --- a/src/Microsoft.TestPlatform.Common/Constants.cs +++ b/src/Microsoft.TestPlatform.Common/Constants.cs @@ -12,7 +12,7 @@ public static class TestPlatformDefaults /// string in the vstest.console.exe.config that specifies the bound on no of jobs in the job queue. /// public const string MaxNumberOfEventsLoggerEventQueueCanHold = "MaxNumberOfEventsLoggerEventQueueCanHold"; - + /// /// Default bound on the job queue. /// diff --git a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs index 8aed93ac90..af000b0ec9 100644 --- a/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs +++ b/src/Microsoft.TestPlatform.Common/ExtensionFramework/TestPluginDiscoverer.cs @@ -7,14 +7,18 @@ 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.Xml; 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; + using CommonResources = Microsoft.VisualStudio.TestPlatform.Common.Resources.Resources; /// /// Discovers test extensions in a directory. @@ -23,6 +27,8 @@ internal class TestPluginDiscoverer { private IFileHelper fileHelper; + private static List UnloadableFiles = new List(); + /// /// Initializes a new instance of the class. /// @@ -128,6 +134,10 @@ private void GetTestExtensionsFromFiles( // Scan each of the files for data extensions. foreach (var file in files) { + if (UnloadableFiles.Contains(file)) + { + continue; + } try { Assembly assembly = null; @@ -138,10 +148,16 @@ private void GetTestExtensionsFromFiles( this.GetTestExtensionsFromAssembly(assembly, pluginInfos); } } + catch (FileLoadException e) + { + EqtTrace.Warning("TestPluginDiscoverer-FileLoadException: Failed to load extensions from file '{0}'. Skipping test extension scan for this file. Error: {1}", file, e); + string fileLoadErrorMessage = string.Format(CultureInfo.CurrentUICulture, CommonResources.FailedToLoadAdapaterFile, file); + TestSessionMessageLogger.Instance.SendMessage(TestMessageLevel.Warning, fileLoadErrorMessage); + UnloadableFiles.Add(file); + } catch (Exception e) { EqtTrace.Warning("TestPluginDiscoverer: Failed to load extensions from file '{0}'. Skipping test extension scan for this file. Error: {1}", file, e); - continue; } } } @@ -161,8 +177,8 @@ private void GetTestExtensionsFromAssembly(Assembly ass { Debug.Assert(assembly != null, "null assembly"); Debug.Assert(pluginInfos != null, "null pluginInfos"); - Type[] types; + try { types = assembly.GetTypes(); @@ -178,7 +194,6 @@ private void GetTestExtensionsFromAssembly(Assembly ass EqtTrace.Warning("LoaderExceptions: {0}", ex); } } - return; } 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..7828159fca 100644 --- a/src/Microsoft.TestPlatform.Common/Interfaces/Engine/TesthostProtocol/IExecutionManager.cs +++ b/src/Microsoft.TestPlatform.Common/Interfaces/Engine/TesthostProtocol/IExecutionManager.cs @@ -18,7 +18,7 @@ public interface IExecutionManager /// Initializes the execution manager. /// /// The path to additional extensions. - void Initialize(IEnumerable pathToAdditionalExtensions); + void Initialize(IEnumerable pathToAdditionalExtensions, ITestMessageEventHandler testMessageEventsHandler); /// /// Starts the test run with sources. diff --git a/src/Microsoft.TestPlatform.Common/Resources/Resources.Designer.cs b/src/Microsoft.TestPlatform.Common/Resources/Resources.Designer.cs index 8dfb3feae7..08e4897357 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/Resources.Designer.cs +++ b/src/Microsoft.TestPlatform.Common/Resources/Resources.Designer.cs @@ -10,7 +10,6 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.Resources { using System; - using System.Reflection; /// @@ -20,7 +19,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.Resources { // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -40,7 +39,7 @@ internal Resources() { internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.VisualStudio.TestPlatform.Common.Resources.Resources", typeof(Resources).GetTypeInfo().Assembly); + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.VisualStudio.TestPlatform.Common.Resources.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; @@ -169,6 +168,15 @@ internal static string FailedToFindInstalledUnitTestExtensions { } } + /// + /// Looks up a localized string similar to Failed to load extensions from file '{0}'. Please use /diag for more information.. + /// + internal static string FailedToLoadAdapaterFile { + get { + return ResourceManager.GetString("FailedToLoadAdapaterFile", resourceCulture); + } + } + /// /// Looks up a localized string similar to An error occured while creating Fast filter.. /// diff --git a/src/Microsoft.TestPlatform.Common/Resources/Resources.resx b/src/Microsoft.TestPlatform.Common/Resources/Resources.resx index 450bf809c0..8e03b8fcdb 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/Resources.resx +++ b/src/Microsoft.TestPlatform.Common/Resources/Resources.resx @@ -153,6 +153,9 @@ Failed to find the list of installed unit test extensions. Reason: {0} + + Failed to load extensions from file '{0}'. Please use /diag for more information. + An error occured while creating Fast filter. diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.cs.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.cs.xlf index 66ef328d0b..66e157470b 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.cs.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.cs.xlf @@ -269,6 +269,11 @@ Operace se ruší na základě žádosti. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.de.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.de.xlf index 0a849def77..9d6b73864f 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.de.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.de.xlf @@ -269,6 +269,11 @@ Der Vorgang wird gemäß Anforderung abgebrochen. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.es.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.es.xlf index 37a25b277e..4d3bcaa7e1 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.es.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.es.xlf @@ -269,6 +269,11 @@ La operación se cancelará como se ha solicitado. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.fr.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.fr.xlf index 223b1eb528..0516749dbe 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.fr.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.fr.xlf @@ -269,6 +269,11 @@ Annulation de l'opération, comme demandé. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.it.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.it.xlf index 538357807d..d5f51a31bf 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.it.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.it.xlf @@ -269,6 +269,11 @@ L'operazione verrà annullata come richiesto. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ja.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ja.xlf index ff37a71693..751f4150bf 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ja.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ja.xlf @@ -269,6 +269,11 @@ 操作のキャンセルが要求されたため、キャンセルしています。 + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ko.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ko.xlf index 31ebab2400..ffe3f7311b 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ko.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ko.xlf @@ -269,6 +269,11 @@ 요청한 대로 작업을 취소하는 중입니다. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.pl.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.pl.xlf index 2ed8d83aac..93081acbba 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.pl.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.pl.xlf @@ -269,6 +269,11 @@ Anulowanie operacji zgodnie z żądaniem. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.pt-BR.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.pt-BR.xlf index 1f57678b09..85c6c0b355 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.pt-BR.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.pt-BR.xlf @@ -269,6 +269,11 @@ Cancelando a operação conforme solicitado. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ru.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ru.xlf index 56ec3f06e3..c326d2179d 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ru.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.ru.xlf @@ -269,6 +269,11 @@ Операция отменяется в соответствии с запросом. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.tr.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.tr.xlf index 36aa10339c..42bb585f21 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.tr.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.tr.xlf @@ -269,6 +269,11 @@ İşlem istek üzerine iptal ediliyor. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.xlf index a89f0855a0..e83ed26f2b 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.xlf @@ -146,6 +146,11 @@ Cancelling the operation as requested. + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.zh-Hans.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.zh-Hans.xlf index b0c5218f28..9fd21e69a7 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.zh-Hans.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.zh-Hans.xlf @@ -269,6 +269,11 @@ 按要求取消该操作。 + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.zh-Hant.xlf b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.zh-Hant.xlf index 5c3231c90d..af7b8773d7 100644 --- a/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.zh-Hant.xlf +++ b/src/Microsoft.TestPlatform.Common/Resources/xlf/Resources.zh-Hant.xlf @@ -269,6 +269,11 @@ 正在應要求取消作業。 + + Failed to load extensions from file '{0}'. Please use /diag for more information. + TestPluginDiscoverer: Failed to load extensions from file '{0}'. Please use /diag for more information. + + \ No newline at end of file diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestInitializeEventsHandler.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestInitializeEventsHandler.cs new file mode 100644 index 0000000000..64b7ba6194 --- /dev/null +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/EventHandlers/TestInitializeEventsHandler.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.EventHandlers +{ + using System; + using System.Collections.Generic; + + using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; + using Microsoft.VisualStudio.TestPlatform.ObjectModel; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; + + /// + /// The test run events handler. + /// + public class TestInitializeEventsHandler : ITestMessageEventHandler + { + private ITestRequestHandler requestHandler; + + /// + /// Initializes a new instance of the class. + /// + /// test request handler + public TestInitializeEventsHandler(ITestRequestHandler requestHandler) + { + this.requestHandler = requestHandler; + } + + /// + /// 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.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..a266585f5f 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Discovery/DiscoveryManager.cs @@ -63,10 +63,10 @@ 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.testPlatformEventSource.AdapterSearchStart(); - + this.testDiscoveryEventsHandler = eventHandler; if (pathToAdditionalExtensions != null && pathToAdditionalExtensions.Any()) { // Start using these additional extensions @@ -76,6 +76,7 @@ public void Initialize(IEnumerable pathToAdditionalExtensions) // Load and Initialize extensions. TestDiscoveryExtensionManager.LoadAndInitializeAllExtensions(false); this.testPlatformEventSource.AdapterSearchStop(); + } /// @@ -107,6 +108,7 @@ public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEve } } + // If there are sources to discover if (verifiedExtensionSourceMap.Any()) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs index b6c81e7fc6..3149b022d9 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/EventHandlers/TestRequestHandler.cs @@ -240,10 +240,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 +266,11 @@ public void OnMessageReceived(object sender, MessageReceivedEventArgs messageRec { EqtTrace.Info("Execution Session Initialize."); this.testHostManagerFactoryReady.Wait(); + var testInitializeEventsHandler = new TestInitializeEventsHandler(this); var pathToAdditionalExtensions = this.dataSerializer.DeserializePayload>(message); jobQueue.QueueJob( () => - testHostManagerFactory.GetExecutionManager().Initialize(pathToAdditionalExtensions), 0); + testHostManagerFactory.GetExecutionManager().Initialize(pathToAdditionalExtensions, testInitializeEventsHandler), 0); break; } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/ExecutionManager.cs index 9a94039b62..25b0dd299e 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; /// @@ -28,16 +30,18 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution public class ExecutionManager : IExecutionManager { private readonly ITestPlatformEventSource testPlatformEventSource; - private BaseRunTests activeTestRun; - private IRequestData requestData; + private readonly TestSessionMessageLogger sessionMessageLogger; + private ITestMessageEventHandler testMessageEventsHandler; /// /// Initializes a new instance of the class. /// public ExecutionManager(IRequestData requestData) : this(TestPlatformEventSource.Instance, requestData) { + this.sessionMessageLogger = TestSessionMessageLogger.Instance; + this.sessionMessageLogger.TestRunMessage += this.TestSessionMessageHandler; } /// @@ -56,8 +60,9 @@ protected ExecutionManager(ITestPlatformEventSource testPlatformEventSource, IRe /// Initializes the execution manager. /// /// The path to additional extensions. - public void Initialize(IEnumerable pathToAdditionalExtensions) + public void Initialize(IEnumerable pathToAdditionalExtensions, ITestMessageEventHandler testMessageEventsHandler) { + this.testMessageEventsHandler = testMessageEventsHandler; this.testPlatformEventSource.AdapterSearchStart(); if (pathToAdditionalExtensions != null && pathToAdditionalExtensions.Any()) @@ -68,7 +73,10 @@ public void Initialize(IEnumerable pathToAdditionalExtensions) this.LoadExtensions(); - this.testPlatformEventSource.AdapterSearchStop(); + //unsubscrive session logger + this.sessionMessageLogger.TestRunMessage -= this.TestSessionMessageHandler; + + this.testPlatformEventSource.AdapterSearchStop(); } /// @@ -96,7 +104,7 @@ public void StartTestRun( this.activeTestRun.RunTests(); } - catch(Exception e) + catch (Exception e) { runEventsHandler.HandleLogMessage(ObjectModel.Logging.TestMessageLevel.Error, e.ToString()); this.Abort(runEventsHandler); @@ -127,12 +135,13 @@ public void StartTestRun( try { this.InitializeDataCollectors(runSettings, testCaseEventsHandler as ITestEventsPublisher, TestSourcesUtility.GetDefaultCodebasePath(tests)); - + this.activeTestRun = new RunTestsWithTests(this.requestData, tests, package, runSettings, testExecutionContext, testCaseEventsHandler, runEventsHandler); this.activeTestRun.RunTests(); + } - catch(Exception e) + catch (Exception e) { runEventsHandler.HandleLogMessage(ObjectModel.Logging.TestMessageLevel.Error, e.ToString()); this.Abort(runEventsHandler); @@ -215,7 +224,7 @@ private void InitializeDataCollectors(string runSettings, ITestEventsPublisher t { var outOfProcDataCollectionManager = new ProxyOutOfProcDataCollectionManager(DataCollectionTestCaseEventSender.Instance, testEventsPublisher); } - + // Initialize inproc data collectors if declared in run settings. if (XmlRunSettingsUtilities.IsInProcDataCollectionEnabled(runSettings)) { @@ -223,6 +232,23 @@ private void InitializeDataCollectors(string runSettings, ITestEventsPublisher t } } + private void TestSessionMessageHandler(object sender, TestRunMessageEventArgs e) + { + if (this.testMessageEventsHandler != null) + { + this.testMessageEventsHandler.HandleLogMessage(e.Level, e.Message); + } + else + { + if (EqtTrace.IsWarningEnabled) + { + EqtTrace.Warning( + "ExecutionManager: Could not pass the log message '{0}' as the callback is null.", + e.Message); + } + } + } + #endregion } } diff --git a/src/vstest.console/Internal/ConsoleLogger.cs b/src/vstest.console/Internal/ConsoleLogger.cs index de6e74da9b..9a2c8367d0 100644 --- a/src/vstest.console/Internal/ConsoleLogger.cs +++ b/src/vstest.console/Internal/ConsoleLogger.cs @@ -181,7 +181,7 @@ public void Initialize(TestLoggerEvents events, string testRunDirectory) // Progress indicator needs to be displayed only for cli experience. this.progressIndicator = new ProgressIndicator(Output, new ConsoleHelper()); } - + // Register for the events. events.TestRunMessage += this.TestMessageHandler; events.TestResult += this.TestResultHandler; @@ -517,7 +517,7 @@ private void TestResultHandler(object sender, TestResultEventArgs e) { break; } - + // Pause the progress indicator before displaying test result information this.progressIndicator?.Pause(); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyDiscoveryManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyDiscoveryManagerTests.cs index 688344b21e..451af19c94 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyDiscoveryManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyDiscoveryManagerTests.cs @@ -48,8 +48,7 @@ public void TestCleanup() public void DiscoverTestsShouldCallInitialize() { var manualResetEvent = new ManualResetEvent(false); - - this.mockDiscoveryManager.Setup(o => o.Initialize(Enumerable.Empty())).Callback( + this.mockDiscoveryManager.Setup(o => o.Initialize(Enumerable.Empty(), null)).Callback( () => manualResetEvent.Set()); var discoveryCriteria = new DiscoveryCriteria(new[] { "test.dll" }, 1, string.Empty); @@ -62,7 +61,7 @@ public void DiscoverTestsShouldCallInitialize() public void DiscoverTestsShouldUpdateTestPluginCacheWithExtensionsReturnByTestHost() { var manualResetEvent = new ManualResetEvent(false); - this.mockDiscoveryManager.Setup(o => o.Initialize(Enumerable.Empty())).Callback( + this.mockDiscoveryManager.Setup(o => o.Initialize(Enumerable.Empty(), null)).Callback( () => manualResetEvent.Set()); this.mockTestHostManager.Setup(o => o.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new List { "C:\\DiscoveryDummy.dll" }); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs index 47851d21e7..0003712027 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/InProcessProxyexecutionManagerTests.cs @@ -48,9 +48,10 @@ public void TestCleanup() public void StartTestRunShouldCallInitialize() { var testRunCriteria = new TestRunCriteria(new List { "source.dll" }, 10); + var mockTestMessageEventHandler = new Mock(); 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(), It.IsAny()), Times.Once, "StartTestRun should call Initialize if not already initialized"); } [TestMethod] diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscoveryManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscoveryManagerTests.cs index 622c2c5583..fd01fbd8ce 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscoveryManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Discovery/DiscoveryManagerTests.cs @@ -10,10 +10,12 @@ namespace TestPlatform.CrossPlatEngine.UnitTests.Discovery using System.Reflection; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; + using Microsoft.VisualStudio.TestPlatform.Common.Logging; using Microsoft.VisualStudio.TestPlatform.Common.Telemetry; using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Discovery; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; + using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -29,12 +31,14 @@ public class DiscoveryManagerTests private DiscoveryManager discoveryManager; private Mock mockRequestData; private Mock mockMetricsCollection; + private TestSessionMessageLogger sessionLogger; [TestInitialize] public void TestInit() { this.mockRequestData = new Mock(); this.mockMetricsCollection = new Mock(); + this.sessionLogger = TestSessionMessageLogger.Instance; this.mockRequestData.Setup(rd => rd.MetricsCollection).Returns(this.mockMetricsCollection.Object); this.discoveryManager = new DiscoveryManager(this.mockRequestData.Object); } @@ -52,11 +56,12 @@ public void TestCleanup() public void InitializeShouldUpdateAdditionalExtenions() { var mockFileHelper = new Mock(); + var mockLogger = new Mock(); mockFileHelper.Setup(fh => fh.DirectoryExists(It.IsAny())).Returns(false); TestPluginCache.Instance = new TestableTestPluginCache(); this.discoveryManager.Initialize( - new string[] { typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location }); + new string[] { typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location }, mockLogger.Object); var allDiscoverers = TestDiscoveryExtensionManager.Create().Discoverers; @@ -147,7 +152,7 @@ public void DiscoverTestsShouldDiscoverTestsInTheSpecifiedSource() var mockLogger = new Mock(); this.discoveryManager.DiscoverTests(criteria, mockLogger.Object); - + // Assert that the tests are passed on via the handletestruncomplete event. mockLogger.Verify(l => l.HandleDiscoveryComplete(It.IsAny(), It.IsAny>()), Times.Once); } @@ -221,6 +226,25 @@ public void DiscoverTestsShouldCollectMetrics() mockMetricsCollector.Verify(rd => rd.Add(TelemetryDataConstants.TotalTestsDiscovered, It.IsAny()), Times.Once); } + [TestMethod] + public void DiscoveryInitializeShouldVerifyWarningMessageIfAdapterFailedToLoad() + { + var assemblyLocation = typeof(DiscoveryManagerTests).GetTypeInfo().Assembly.Location; + var mockLogger = new Mock(); + TestPluginCacheTests.SetupMockExtensions( + new string[] { assemblyLocation }, + () => { }); + + //Act + this.discoveryManager.Initialize(new List { assemblyLocation }, mockLogger.Object); + + //when handler instance returns warning + sessionLogger.SendMessage(TestMessageLevel.Warning, "verify that the HandleLogMessage method getting invoked at least once"); + + // Verify. + mockLogger.Verify(rd => rd.HandleLogMessage(TestMessageLevel.Warning, "verify that the HandleLogMessage method getting invoked at least once"), Times.Once); + } + #endregion } } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/EventHandlers/TestRequestHandlerTests.cs index 912aa8ee75..4b5d5a2d24 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"))), It.IsAny())); this.SendSessionEnd(); } @@ -218,13 +218,12 @@ public void DiscoveryCompleteShouldSendDiscoveryCompletePayloadOnChannel() public void ProcessRequestsExecutionInitializeShouldSetExtensionPaths() { var message = this.dataSerializer.SerializePayload(MessageType.ExecutionInitialize, new[] { "testadapter.dll" }); - this.ProcessRequestsAsync(this.mockTestHostManagerFactory.Object); 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"))), It.IsAny())); this.SendSessionEnd(); } diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs index 6bc96678c4..8424a56775 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Execution/ExecutionManagerTests.cs @@ -11,6 +11,7 @@ namespace TestPlatform.CrossPlatEngine.UnitTests.Execution using Microsoft.VisualStudio.TestPlatform.Common; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework; using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework.Utilities; + using Microsoft.VisualStudio.TestPlatform.Common.Logging; using Microsoft.VisualStudio.TestPlatform.Common.SettingsProvider; using Microsoft.VisualStudio.TestPlatform.Common.Telemetry; using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution; @@ -33,16 +34,18 @@ public class ExecutionManagerTests private ExecutionManager executionManager; private TestExecutionContext testExecutionContext; private Mock mockRequestData; + private TestSessionMessageLogger sessionLogger; [TestInitialize] public void TestInit() { this.mockRequestData = new Mock(); this.mockRequestData.Setup(rd => rd.MetricsCollection).Returns(new NoOpMetricsCollection()); + this.sessionLogger = TestSessionMessageLogger.Instance; this.executionManager = new ExecutionManager(new RequestData - { - MetricsCollection = new NoOpMetricsCollection() - }); + { + MetricsCollection = new NoOpMetricsCollection() + }); TestPluginCache.Instance = null; @@ -74,13 +77,13 @@ public void TestCleanup() public void InitializeShouldLoadAndInitializeAllExtension() { var commonAssemblyLocation = typeof(TestPluginCacheTests).GetTypeInfo().Assembly.Location; - + var mockTestMessageEventHandler = new Mock(); TestPluginCacheTests.SetupMockExtensions( new string[] { commonAssemblyLocation }, () => { }); - this.executionManager.Initialize(new List { commonAssemblyLocation }); + this.executionManager.Initialize(new List { commonAssemblyLocation }, mockTestMessageEventHandler.Object); Assert.IsNotNull(TestPluginCache.Instance.TestExtensions); @@ -210,5 +213,35 @@ public void StartTestRunShouldAbortTheRunIfAnyExceptionComesForTheProvidedSource mockTestRunEventsHandler.Verify(treh => treh.HandleTestRunComplete(It.IsAny(), null, null, null), Times.Once); mockTestRunEventsHandler.Verify(treh => treh.HandleLogMessage(TestMessageLevel.Error, It.IsAny()), Times.Once); } + + //[TestMethod] + //public void InitializeShouldVerifyWarningMessageIfAdapterFailedToLoad() + //{ + // var assemblyLocation = typeof(ExecutionManagerTests).GetTypeInfo().Assembly.Location; + // var mockLogger = new Mock(); + // TestPluginCacheTests.SetupMockExtensions( + // new string[] { assemblyLocation }, + // () => { }); + // //Act + // this.executionManager.Initialize(new List { assemblyLocation }, mockLogger.Object); + + // //when handler instance returns warning + // sessionLogger.SendMessage(TestMessageLevel.Warning, "verify that it is downgraded to warning"); + + // // Verify. + // mockLogger.Verify(rd => rd.HandleLogMessage(TestMessageLevel.Warning, "verify that it is downgraded to warning"), Times.Once); + //} + + [TestMethod] + public void InitializeShouldVerifyTheHandlerInitializationWhenAdapterIsFailedToLoad() + { + var mockLogger = new Mock(); + + //when handler instance is null + sessionLogger.SendMessage(It.IsAny(), "verify that the HandleLogMessage method will not be invoked when handler is not initialized"); + + // Verify. + mockLogger.Verify(rd => rd.HandleLogMessage(It.IsAny(), "verify that the HandleLogMessage method will not be invoked when handler is not initialized"), Times.Never); + } } }