diff --git a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleWrapper.cs b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleWrapper.cs index f128e7cc58..672d9b4164 100644 --- a/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleWrapper.cs +++ b/src/Microsoft.TestPlatform.VsTestConsole.TranslationLayer/VsTestConsoleWrapper.cs @@ -5,14 +5,20 @@ namespace Microsoft.TestPlatform.VsTestConsole.TranslationLayer { using System.Collections.Generic; using System.Diagnostics; + using System.Globalization; using System.Linq; using Microsoft.TestPlatform.VsTestConsole.TranslationLayer.Interfaces; + using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Helpers; using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing; using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing.Interfaces; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces; + using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; + using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; + using CommunicationUtilitiesResources = Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Resources.Resources; + using CoreUtilitiesConstants = Microsoft.VisualStudio.TestPlatform.CoreUtilities.Constants; /// /// An implementation of to invoke test operations @@ -28,6 +34,8 @@ public class VsTestConsoleWrapper : IVsTestConsoleWrapper private readonly ITranslationLayerRequestSender requestSender; + private readonly IProcessHelper processHelper; + private bool sessionStarted; /// @@ -63,7 +71,7 @@ public VsTestConsoleWrapper(string vstestConsolePath) : /// Path to the test runner vstest.console.exe. /// The parameters to be passed onto the runner process public VsTestConsoleWrapper(string vstestConsolePath, ConsoleParameters consoleParameters) : - this(new VsTestConsoleRequestSender(), new VsTestConsoleProcessManager(vstestConsolePath), consoleParameters, TestPlatformEventSource.Instance) + this(new VsTestConsoleRequestSender(), new VsTestConsoleProcessManager(vstestConsolePath), consoleParameters, TestPlatformEventSource.Instance, new ProcessHelper()) { } @@ -74,12 +82,14 @@ public VsTestConsoleWrapper(string vstestConsolePath, ConsoleParameters consoleP /// Process manager. /// The parameters to be passed onto the runner process /// Performance event source - internal VsTestConsoleWrapper(ITranslationLayerRequestSender requestSender, IProcessManager processManager, ConsoleParameters consoleParameters, ITestPlatformEventSource testPlatformEventSource) + /// Helper for process related utilities + internal VsTestConsoleWrapper(ITranslationLayerRequestSender requestSender, IProcessManager processManager, ConsoleParameters consoleParameters, ITestPlatformEventSource testPlatformEventSource, IProcessHelper processHelper) { this.requestSender = requestSender; this.vstestConsoleProcessManager = processManager; this.consoleParameters = consoleParameters; this.testPlatformEventSource = testPlatformEventSource; + this.processHelper = processHelper; this.pathToAdditionalExtensions = new List(); this.vstestConsoleProcessManager.ProcessExited += (sender, args) => this.requestSender.OnProcessExited(); @@ -263,20 +273,29 @@ private void EnsureInitialized() EqtTrace.Info("VsTestConsoleWrapper.EnsureInitialized: Process Started."); this.sessionStarted = this.WaitForConnection(); } - - if (!this.sessionStarted) - { - throw new TransationLayerException("Error connecting to Vstest Command Line"); - } } private bool WaitForConnection() { EqtTrace.Info("VsTestConsoleWrapper.WaitForConnection: Waiting for connection to command line runner."); - var connected = this.requestSender.WaitForRequestHandlerConnection(ConnectionTimeout); - this.testPlatformEventSource.TranslationLayerInitializeStop(); - return connected; + var timeout = EnvironmentHelper.GetConnectionTimeout(); + if (!this.requestSender.WaitForRequestHandlerConnection(timeout * 1000)) + { + var processName = this.processHelper.GetCurrentProcessFileName(); + throw new TransationLayerException( + string.Format( + CultureInfo.CurrentUICulture, + CommunicationUtilitiesResources.ConnectionTimeoutErrorMessage, + processName, + CoreUtilitiesConstants.VstestConsoleProcessName, + timeout, + EnvironmentHelper.VstestConnectionTimeout) + ); + } + + this.testPlatformEventSource.TranslationLayerInitializeStop(); + return true; } } } diff --git a/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs b/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs index 1c7f158755..02d2b79de1 100644 --- a/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs +++ b/test/TranslationLayer.UnitTests/VsTestConsoleWrapperTests.cs @@ -11,6 +11,7 @@ namespace Microsoft.TestPlatform.VsTestConsole.TranslationLayer.UnitTests using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces; + using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -23,6 +24,8 @@ public class VsTestConsoleWrapperTests private Mock mockProcessManager; + private Mock mockProcessHelper; + private Mock mockRequestSender; private readonly List testSources = new List { "Hello", "World" }; @@ -42,11 +45,13 @@ public void TestInitialize() this.mockRequestSender = new Mock(); this.mockProcessManager = new Mock(); + this.mockProcessHelper = new Mock(); this.consoleWrapper = new VsTestConsoleWrapper( this.mockRequestSender.Object, this.mockProcessManager.Object, this.consoleParameters, - new Mock().Object); + new Mock().Object, + this.mockProcessHelper.Object); this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); this.mockRequestSender.Setup(rs => rs.InitializeCommunication()).Returns(100); @@ -124,9 +129,11 @@ public void InitializeExtensionsShouldSucceed() [TestMethod] public void InitializeExtensionsShouldThrowExceptionOnBadConnection() { + this.mockProcessHelper.Setup(x => x.GetCurrentProcessFileName()).Returns("DummyProcess"); this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); - Assert.ThrowsException(() => this.consoleWrapper.InitializeExtensions(new List { "Hello", "World" })); + var exception = Assert.ThrowsException(() => this.consoleWrapper.InitializeExtensions(new List { "Hello", "World" })); + Assert.AreEqual("DummyProcess process failed to connect to vstest.console process after 90 seconds. This may occur due to machine slowness, please set environment variable VSTEST_CONNECTION_TIMEOUT to increase timeout.", exception.Message); this.mockRequestSender.Verify(rs => rs.InitializeExtensions(It.IsAny>()), Times.Never); } @@ -158,9 +165,11 @@ public void DiscoverTestsShouldCallTestDiscoveryHandler2IfTestDiscoveryHandler1I [TestMethod] public void DiscoverTestsShouldThrowExceptionOnBadConnection() { + this.mockProcessHelper.Setup(x => x.GetCurrentProcessFileName()).Returns("DummyProcess"); this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); - Assert.ThrowsException(() => this.consoleWrapper.DiscoverTests(new List { "Hello", "World" }, null, null, new Mock().Object)); + var exception = Assert.ThrowsException(() => this.consoleWrapper.DiscoverTests(new List { "Hello", "World" }, null, null, new Mock().Object)); + Assert.AreEqual("DummyProcess process failed to connect to vstest.console process after 90 seconds. This may occur due to machine slowness, please set environment variable VSTEST_CONNECTION_TIMEOUT to increase timeout.", exception.Message); this.mockRequestSender.Verify(rs => rs.DiscoverTests(It.IsAny>(), It.IsAny(), null, It.IsAny()), Times.Never); }