From a8b1e78b9e84594f9f22ca3f82c486d0096135f7 Mon Sep 17 00:00:00 2001 From: Abhishek Kumawat Date: Mon, 23 Apr 2018 19:19:51 +0530 Subject: [PATCH] Cancel/abort not honored when sent before custom host launch (#1543) * Cancellation in custom host launcher, test host, while ongoing communication * passing cancellation to data collectors. * Passing operation canceled instead of test platform exception to translation layer. --- .../Program.cs | 7 +- .../DesignMode/DesignModeClient.cs | 10 +- .../DesignMode/DesignModeTestHostLauncher.cs | 9 +- .../DesignMode/IDesignModeClient.cs | 7 +- .../Execution/TestRunRequest.cs | 9 +- .../DataCollectionRequestSender.cs | 2 +- .../Interfaces/ITestRequestSender.cs | 4 +- .../TestRequestSender.cs | 13 ++- .../Client/ProxyDiscoveryManager.cs | 4 +- .../Client/ProxyExecutionManager.cs | 19 ++-- ...ProxyExecutionManagerWithDataCollection.cs | 15 +-- .../Client/ProxyOperationManager.cs | 14 ++- .../DataCollectionTestRunEventsHandler.cs | 11 +- .../Execution/BaseRunTests.cs | 3 + .../Client/Interfaces/ITestHostLauncher.cs | 10 ++ .../Hosting/DefaultTestHostManager.cs | 31 ++--- .../Hosting/DotnetTestHostManager.cs | 31 ++--- .../TestPlatformHelpers/TestRequestManager.cs | 8 -- .../CustomTestHostLauncher.cs | 12 +- .../DesignMode/DesignModeClientTests.cs | 17 ++- .../DesignModeTestHostLauncherTests.cs | 4 +- .../DataCollectionRequestSenderTests.cs | 62 ++++++++++ .../TestRequestSenderTests.cs | 13 ++- .../Client/ProxyDiscoveryManagerTests.cs | 24 ++-- .../Client/ProxyExecutionManagerTests.cs | 86 +++++++++----- ...ExecutionManagerWithDataCollectionTests.cs | 19 ---- .../Client/ProxyOperationManagerTests.cs | 107 ++++++++++-------- ...DataCollectionTestRunEventsHandlerTests.cs | 43 ++++++- .../Hosting/DefaultTestHostManagerTests.cs | 6 +- .../Hosting/DotnetTestHostManagerTests.cs | 8 +- .../TestRequestManagerTests.cs | 76 ------------- 31 files changed, 386 insertions(+), 298 deletions(-) create mode 100644 test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionRequestSenderTests.cs diff --git a/samples/Microsoft.TestPlatform.TranslationLayer.E2ETest/Program.cs b/samples/Microsoft.TestPlatform.TranslationLayer.E2ETest/Program.cs index 7ac4f60bb5..faa74b3763 100644 --- a/samples/Microsoft.TestPlatform.TranslationLayer.E2ETest/Program.cs +++ b/samples/Microsoft.TestPlatform.TranslationLayer.E2ETest/Program.cs @@ -168,7 +168,7 @@ public CustomTestHostLauncher(Action callback) public bool IsDebug => false; - public int LaunchTestHost(TestProcessStartInfo defaultTestHostStartInfo) + public int LaunchTestHost(TestProcessStartInfo defaultTestHostStartInfo, CancellationToken cancellationToken) { var processInfo = new ProcessStartInfo( defaultTestHostStartInfo.FileName, @@ -192,6 +192,11 @@ public int LaunchTestHost(TestProcessStartInfo defaultTestHostStartInfo) throw new Exception("Process in invalid state."); } + + public int LaunchTestHost(TestProcessStartInfo defaultTestHostStartInfo) + { + return this.LaunchTestHost(defaultTestHostStartInfo, CancellationToken.None); + } } public class DiscoveryEventHandler : ITestDiscoveryEventsHandler diff --git a/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs b/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs index 6d8f1bb033..ab2c6f31f8 100644 --- a/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs +++ b/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeClient.cs @@ -235,10 +235,13 @@ private void ProcessRequests(ITestRequestManager testRequestManager) /// /// The test Process Start Info. /// + /// + /// The cancellation token. + /// /// /// The . /// - public int LaunchCustomHost(TestProcessStartInfo testProcessStartInfo) + public int LaunchCustomHost(TestProcessStartInfo testProcessStartInfo, CancellationToken cancellationToken) { lock (ackLockObject) { @@ -257,7 +260,10 @@ public int LaunchCustomHost(TestProcessStartInfo testProcessStartInfo) // Even if TP has a timeout here, there is no way TP can abort or stop the thread/task that is hung in IDE or LUT // Even if TP can abort the API somehow, TP is essentially putting IDEs or Clients in inconsistent state without having info on // Since the IDEs own user-UI-experience here, TP will let the custom host launch as much time as IDEs define it for their users - waitHandle.WaitOne(); + WaitHandle.WaitAny(new WaitHandle[] { waitHandle, cancellationToken.WaitHandle }); + + cancellationToken.ThrowIfCancellationRequested(); + this.onAckMessageReceived = null; var ackPayload = this.dataSerializer.DeserializePayload(ackMessage); diff --git a/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeTestHostLauncher.cs b/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeTestHostLauncher.cs index 92f5fe8291..bc84515c49 100644 --- a/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeTestHostLauncher.cs +++ b/src/Microsoft.TestPlatform.Client/DesignMode/DesignModeTestHostLauncher.cs @@ -3,6 +3,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Client.DesignMode { + using System.Threading; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces; @@ -28,7 +29,13 @@ public DesignModeTestHostLauncher(IDesignModeClient designModeClient) /// public int LaunchTestHost(TestProcessStartInfo defaultTestHostStartInfo) { - return this.designModeClient.LaunchCustomHost(defaultTestHostStartInfo); + return this.designModeClient.LaunchCustomHost(defaultTestHostStartInfo, CancellationToken.None); + } + + /// + public int LaunchTestHost(TestProcessStartInfo defaultTestHostStartInfo, CancellationToken cancellationToken) + { + return this.designModeClient.LaunchCustomHost(defaultTestHostStartInfo, cancellationToken); } } diff --git a/src/Microsoft.TestPlatform.Client/DesignMode/IDesignModeClient.cs b/src/Microsoft.TestPlatform.Client/DesignMode/IDesignModeClient.cs index 05399ac9eb..75daa1eb98 100644 --- a/src/Microsoft.TestPlatform.Client/DesignMode/IDesignModeClient.cs +++ b/src/Microsoft.TestPlatform.Client/DesignMode/IDesignModeClient.cs @@ -3,9 +3,10 @@ namespace Microsoft.VisualStudio.TestPlatform.Client.DesignMode { + using System; + using System.Threading; using Microsoft.VisualStudio.TestPlatform.Client.RequestHelper; using Microsoft.VisualStudio.TestPlatform.ObjectModel; - using System; /// /// The interface for design mode client. @@ -28,7 +29,9 @@ public interface IDesignModeClient : IDisposable /// Send a custom host launch message to IDE /// /// Default TestHost Start Info - int LaunchCustomHost(TestProcessStartInfo defaultTestHostStartInfo); + /// The cancellation Token. + /// Process id of the launched test host. + int LaunchCustomHost(TestProcessStartInfo defaultTestHostStartInfo, CancellationToken cancellationToken); /// /// Handles parent process exit diff --git a/src/Microsoft.TestPlatform.Client/Execution/TestRunRequest.cs b/src/Microsoft.TestPlatform.Client/Execution/TestRunRequest.cs index 610535289c..a58438532a 100644 --- a/src/Microsoft.TestPlatform.Client/Execution/TestRunRequest.cs +++ b/src/Microsoft.TestPlatform.Client/Execution/TestRunRequest.cs @@ -41,6 +41,11 @@ public class TestRunRequest : ITestRunRequest, ITestRunEventsHandler /// private object syncObject = new Object(); + /// + /// Sync object for cancel operation + /// + private object cancelSyncObject = new Object(); + /// /// The run completion event which will be signalled on completion of test run. /// @@ -236,7 +241,7 @@ public void CancelAsync() { EqtTrace.Verbose("TestRunRequest.CancelAsync: Canceling."); - lock (this.syncObject) + lock (this.cancelSyncObject) { if (this.disposed) { @@ -265,7 +270,7 @@ public void Abort() { EqtTrace.Verbose("TestRunRequest.Abort: Aborting."); - lock (this.syncObject) + lock (this.cancelSyncObject) { if (this.disposed) { diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionRequestSender.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionRequestSender.cs index 40e19c69f6..22b16e4944 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionRequestSender.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/DataCollectionRequestSender.cs @@ -160,7 +160,7 @@ public Collection SendAfterTestRunStartAndGetResult(ITestMessageE // Cycle through the messages that the datacollector sends. // Currently each of the operations are not separate tasks since they should not each take much time. This is just a notification. - while (!isDataCollectionComplete) + while (!isDataCollectionComplete && !isCancelled) { var message = this.communicationManager.ReceiveMessage(); diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/ITestRequestSender.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/ITestRequestSender.cs index e053941fa1..d65aa7bb0f 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/ITestRequestSender.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/Interfaces/ITestRequestSender.cs @@ -5,6 +5,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces { using System; using System.Collections.Generic; + using System.Threading; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client; @@ -29,8 +30,9 @@ public interface ITestRequestSender : IDisposable /// Waits for Request Handler to be connected /// /// Time to wait for connection + /// Cancellation token /// True, if Handler is connected - bool WaitForRequestHandlerConnection(int connectionTimeout); + bool WaitForRequestHandlerConnection(int connectionTimeout, CancellationToken cancellationToken); /// /// Close the Sender diff --git a/src/Microsoft.TestPlatform.CommunicationUtilities/TestRequestSender.cs b/src/Microsoft.TestPlatform.CommunicationUtilities/TestRequestSender.cs index cb16127f5c..89c4b222d0 100644 --- a/src/Microsoft.TestPlatform.CommunicationUtilities/TestRequestSender.cs +++ b/src/Microsoft.TestPlatform.CommunicationUtilities/TestRequestSender.cs @@ -135,14 +135,17 @@ public int InitializeCommunication() } /// - public bool WaitForRequestHandlerConnection(int connectionTimeout) + public bool WaitForRequestHandlerConnection(int connectionTimeout, CancellationToken cancellationToken) { if (EqtTrace.IsVerboseEnabled) { EqtTrace.Verbose("TestRequestSender.WaitForRequestHandlerConnection: waiting for connection with timeout: {0}", connectionTimeout); } - return this.connected.Wait(connectionTimeout); + var waitIndex = WaitHandle.WaitAny(new WaitHandle[] { this.connected.WaitHandle, cancellationToken.WaitHandle }, connectionTimeout); + + // Return true if wait is because of waitHandle. + return waitIndex == 0; } /// @@ -560,8 +563,10 @@ private string GetAbortErrorMessage(Exception exception, bool getClientError) EqtTrace.Info("TestRequestSender: GetAbortErrorMessage: Received test host error message."); reason = this.clientExitErrorMessage; } - - EqtTrace.Info("TestRequestSender: GetAbortErrorMessage: Timed out waiting for test host error message."); + else + { + EqtTrace.Info("TestRequestSender: GetAbortErrorMessage: Timed out waiting for test host error message."); + } } return reason; diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs index 4d735df490..e3168649d8 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyDiscoveryManager.cs @@ -27,7 +27,6 @@ public class ProxyDiscoveryManager : ProxyOperationManager, IProxyDiscoveryManag { private readonly ITestRuntimeProvider testHostManager; private IDataSerializer dataSerializer; - private CancellationTokenSource cancellationTokenSource; private bool isCommunicationEstablished; private IRequestData requestData; private ITestDiscoveryEventsHandler2 baseTestDiscoveryEventsHandler; @@ -67,7 +66,6 @@ internal ProxyDiscoveryManager(IRequestData requestData, { this.dataSerializer = dataSerializer; this.testHostManager = testHostManager; - this.cancellationTokenSource = new CancellationTokenSource(); this.isCommunicationEstablished = false; this.requestData = requestData; } @@ -95,7 +93,7 @@ public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEve this.baseTestDiscoveryEventsHandler = eventHandler; try { - this.isCommunicationEstablished = this.SetupChannel(discoveryCriteria.Sources, this.cancellationTokenSource.Token); + this.isCommunicationEstablished = this.SetupChannel(discoveryCriteria.Sources); if (this.isCommunicationEstablished) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs index 3bb1963620..2e8313bc97 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManager.cs @@ -29,7 +29,6 @@ internal class ProxyExecutionManager : ProxyOperationManager, IProxyExecutionMan { private readonly ITestRuntimeProvider testHostManager; private IDataSerializer dataSerializer; - private CancellationTokenSource cancellationTokenSource; private bool isCommunicationEstablished; private IRequestData requestData; private ITestRunEventsHandler baseTestRunEventsHandler; @@ -65,7 +64,6 @@ internal ProxyExecutionManager(IRequestData requestData, ITestRequestSender requ { this.testHostManager = testHostManager; this.dataSerializer = dataSerializer; - this.cancellationTokenSource = new CancellationTokenSource(); this.isCommunicationEstablished = false; this.requestData = requestData; } @@ -100,16 +98,15 @@ public virtual int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEventsH { EqtTrace.Verbose("ProxyExecutionManager: Test host is always Lazy initialize."); } - var testPackages = new List(testRunCriteria.HasSpecificSources ? testRunCriteria.Sources : // If the test execution is with a test filter, group them by sources testRunCriteria.Tests.GroupBy(tc => tc.Source).Select(g => g.Key)); - this.isCommunicationEstablished = this.SetupChannel(testPackages, this.cancellationTokenSource.Token); + this.isCommunicationEstablished = this.SetupChannel(testPackages); if (this.isCommunicationEstablished) { - if (this.cancellationTokenSource.IsCancellationRequested) + if (this.CancellationTokenSource.IsCancellationRequested) { if (EqtTrace.IsVerboseEnabled) { @@ -139,13 +136,11 @@ public virtual int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEventsH if (testRunCriteria.HasSpecificSources) { var runRequest = testRunCriteria.CreateTestRunCriteriaForSources(testHostManager, runsettings, executionContext, testPackages); - this.RequestSender.StartTestRun(runRequest, this); } else { var runRequest = testRunCriteria.CreateTestRunCriteriaForTests(testHostManager, runsettings, executionContext, testPackages); - this.RequestSender.StartTestRun(runRequest, this); } } @@ -185,7 +180,7 @@ public virtual void Cancel(ITestRunEventsHandler eventHandler) } // Cancel fast, try to stop testhost deployment/launch - this.cancellationTokenSource.Cancel(); + this.CancellationTokenSource.Cancel(); if (this.isCommunicationEstablished) { this.RequestSender.SendTestRunCancel(); @@ -210,7 +205,13 @@ public void Abort(ITestRunEventsHandler eventHandler) this.baseTestRunEventsHandler = eventHandler; } - this.RequestSender.SendTestRunAbort(); + // Cancel fast, try to stop testhost deployment/launch + this.CancellationTokenSource.Cancel(); + + if (this.isCommunicationEstablished) + { + this.RequestSender.SendTestRunAbort(); + } } /// diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManagerWithDataCollection.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManagerWithDataCollection.cs index 31fd0acc0e..7547ecda51 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManagerWithDataCollection.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyExecutionManagerWithDataCollection.cs @@ -112,7 +112,7 @@ public override int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEvents var currentEventHandler = eventHandler; if (this.ProxyDataCollectionManager != null) { - currentEventHandler = new DataCollectionTestRunEventsHandler(eventHandler, this.ProxyDataCollectionManager); + currentEventHandler = new DataCollectionTestRunEventsHandler(eventHandler, this.ProxyDataCollectionManager, this.CancellationTokenSource.Token); } // Log all the messages that are reported while initializing DataCollectionClient @@ -129,19 +129,6 @@ public override int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEvents return base.StartTestRun(testRunCriteria, currentEventHandler); } - /// - public override void Cancel(ITestRunEventsHandler eventHandler) - { - try - { - this.ProxyDataCollectionManager.AfterTestRunEnd(isCanceled: true, runEventsHandler: this.DataCollectionRunEventsHandler); - } - finally - { - base.Cancel(eventHandler); - } - } - public override int LaunchProcessWithDebuggerAttached(TestProcessStartInfo testProcessStartInfo) { if (this.dataCollectionEnvironmentVariables != null) diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs index 912a896cfa..567999ef3d 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Client/ProxyOperationManager.cs @@ -56,6 +56,7 @@ public abstract class ProxyOperationManager protected ProxyOperationManager(IRequestData requestData, ITestRequestSender requestSender, ITestRuntimeProvider testHostManager) { this.RequestSender = requestSender; + this.CancellationTokenSource = new CancellationTokenSource(); this.testHostManager = testHostManager; this.processHelper = new ProcessHelper(); this.initialized = false; @@ -75,6 +76,11 @@ protected ProxyOperationManager(IRequestData requestData, ITestRequestSender req /// protected ITestRequestSender RequestSender { get; set; } + /// + /// Gets or sets the cancellation token source. + /// + protected CancellationTokenSource CancellationTokenSource { get; set; } + #endregion #region IProxyOperationManager implementation. @@ -91,8 +97,9 @@ protected ProxyOperationManager(IRequestData requestData, ITestRequestSender req /// /// Returns true if Communation is established b/w runner and host /// - public virtual bool SetupChannel(IEnumerable sources, CancellationToken cancellationToken) + public virtual bool SetupChannel(IEnumerable sources) { + this.CancellationTokenSource.Token.ThrowIfCancellationRequested(); var connTimeout = EnvironmentHelper.GetConnectionTimeout(); if (!this.initialized) @@ -108,7 +115,6 @@ public virtual bool SetupChannel(IEnumerable sources, CancellationToken } var processId = this.processHelper.GetCurrentProcessId(); - var connectionInfo = new TestRunnerConnectionInfo { Port = portNumber, ConnectionInfo = testHostConnectionInfo, RunnerProcessId = processId, LogFile = this.GetTimestampedLogFile(EqtTrace.LogFile) }; // Subscribe to TestHost Event @@ -120,7 +126,7 @@ public virtual bool SetupChannel(IEnumerable sources, CancellationToken try { // Launch the test host. - var hostLaunchedTask = this.testHostManager.LaunchTestHostAsync(testHostStartInfo, cancellationToken); + var hostLaunchedTask = this.testHostManager.LaunchTestHostAsync(testHostStartInfo, this.CancellationTokenSource.Token); this.testHostLaunched = hostLaunchedTask.Result; if (this.testHostLaunched && testHostConnectionInfo.Role == ConnectionRole.Host) @@ -150,7 +156,7 @@ public virtual bool SetupChannel(IEnumerable sources, CancellationToken // Wait for a timeout for the client to connect. if (!this.testHostLaunched || - !this.RequestSender.WaitForRequestHandlerConnection(connTimeout * 1000)) + !this.RequestSender.WaitForRequestHandlerConnection(connTimeout * 1000, this.CancellationTokenSource.Token)) { this.ThrowExceptionOnConnectionFailure(connTimeout); } diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionTestRunEventsHandler.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionTestRunEventsHandler.cs index 9b36171906..c14dd3c9ad 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionTestRunEventsHandler.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/DataCollection/DataCollectionTestRunEventsHandler.cs @@ -7,6 +7,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.DataCollection using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; + using System.Threading; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; @@ -24,6 +25,7 @@ internal class DataCollectionTestRunEventsHandler : ITestRunEventsHandler { private IProxyDataCollectionManager proxyDataCollectionManager; private ITestRunEventsHandler testRunEventsHandler; + private CancellationToken cancellationToken; private IDataSerializer dataSerializer; private Collection dataCollectionAttachmentSets; @@ -36,8 +38,8 @@ internal class DataCollectionTestRunEventsHandler : ITestRunEventsHandler /// /// The proxy Data Collection Manager. /// - public DataCollectionTestRunEventsHandler(ITestRunEventsHandler baseTestRunEventsHandler, IProxyDataCollectionManager proxyDataCollectionManager) - : this(baseTestRunEventsHandler, proxyDataCollectionManager, JsonDataSerializer.Instance) + public DataCollectionTestRunEventsHandler(ITestRunEventsHandler baseTestRunEventsHandler, IProxyDataCollectionManager proxyDataCollectionManager, CancellationToken cancellationToken) + : this(baseTestRunEventsHandler, proxyDataCollectionManager, cancellationToken, JsonDataSerializer.Instance) { } @@ -53,10 +55,11 @@ public DataCollectionTestRunEventsHandler(ITestRunEventsHandler baseTestRunEvent /// /// The data Serializer. /// - public DataCollectionTestRunEventsHandler(ITestRunEventsHandler baseTestRunEventsHandler, IProxyDataCollectionManager proxyDataCollectionManager, IDataSerializer dataSerializer) + public DataCollectionTestRunEventsHandler(ITestRunEventsHandler baseTestRunEventsHandler, IProxyDataCollectionManager proxyDataCollectionManager, CancellationToken cancellationToken, IDataSerializer dataSerializer) { this.proxyDataCollectionManager = proxyDataCollectionManager; this.testRunEventsHandler = baseTestRunEventsHandler; + this.cancellationToken = cancellationToken; this.dataSerializer = dataSerializer; } @@ -87,7 +90,7 @@ public void HandleRawMessage(string rawMessage) if (string.Equals(MessageType.ExecutionComplete, message.MessageType)) { - this.dataCollectionAttachmentSets = this.proxyDataCollectionManager?.AfterTestRunEnd(false, this); + this.dataCollectionAttachmentSets = this.proxyDataCollectionManager?.AfterTestRunEnd(this.cancellationToken.IsCancellationRequested, this); if (this.dataCollectionAttachmentSets != null && this.dataCollectionAttachmentSets.Any()) { diff --git a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs index fec3391f2d..8361a80d67 100644 --- a/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs +++ b/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/BaseRunTests.cs @@ -287,6 +287,9 @@ internal void Abort() /// internal void Cancel() { + // Note: Test host delegates the cancellation to active executor and doesn't call HandleTestRunComplete in cancel request. + // Its expected from active executor to respect the cancel request and thus return from RunTests quickly (cancelling the tests). + isCancellationRequested = true; if (this.activeExecutor == null) diff --git a/src/Microsoft.TestPlatform.ObjectModel/Client/Interfaces/ITestHostLauncher.cs b/src/Microsoft.TestPlatform.ObjectModel/Client/Interfaces/ITestHostLauncher.cs index bb663ce8e6..b49eaa7a86 100644 --- a/src/Microsoft.TestPlatform.ObjectModel/Client/Interfaces/ITestHostLauncher.cs +++ b/src/Microsoft.TestPlatform.ObjectModel/Client/Interfaces/ITestHostLauncher.cs @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Threading; + namespace Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces { /// @@ -19,5 +21,13 @@ public interface ITestHostLauncher /// Default TestHost Process Info /// Process id of the launched test host int LaunchTestHost(TestProcessStartInfo defaultTestHostStartInfo); + + /// + /// Launches custom test host using the default test process start info + /// + /// Default TestHost Process Info + /// The cancellation Token. + /// Process id of the launched test host + int LaunchTestHost(TestProcessStartInfo defaultTestHostStartInfo, CancellationToken cancellationToken); } } diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs index db0d036239..3d4e8fedcd 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DefaultTestHostManager.cs @@ -369,30 +369,21 @@ private void OnHostExited(HostProviderEventArgs e) private bool LaunchHost(TestProcessStartInfo testHostStartInfo, CancellationToken cancellationToken) { - try - { - this.testHostProcessStdError = new StringBuilder(this.ErrorLength, this.ErrorLength); - EqtTrace.Verbose("Launching default test Host Process {0} with arguments {1}", testHostStartInfo.FileName, testHostStartInfo.Arguments); + this.testHostProcessStdError = new StringBuilder(this.ErrorLength, this.ErrorLength); + EqtTrace.Verbose("Launching default test Host Process {0} with arguments {1}", testHostStartInfo.FileName, testHostStartInfo.Arguments); - if (this.customTestHostLauncher == null) - { - EqtTrace.Verbose("DefaultTestHostManager: Starting process '{0}' with command line '{1}'", testHostStartInfo.FileName, testHostStartInfo.Arguments); + if (this.customTestHostLauncher == null) + { + EqtTrace.Verbose("DefaultTestHostManager: Starting process '{0}' with command line '{1}'", testHostStartInfo.FileName, testHostStartInfo.Arguments); - cancellationToken.ThrowIfCancellationRequested(); - this.testHostProcess = this.processHelper.LaunchProcess(testHostStartInfo.FileName, testHostStartInfo.Arguments, testHostStartInfo.WorkingDirectory, testHostStartInfo.EnvironmentVariables, this.ErrorReceivedCallback, this.ExitCallBack) as Process; - } - else - { - int processId = this.customTestHostLauncher.LaunchTestHost(testHostStartInfo); - this.testHostProcess = Process.GetProcessById(processId); - this.processHelper.SetExitCallback(processId, this.ExitCallBack); - } + cancellationToken.ThrowIfCancellationRequested(); + this.testHostProcess = this.processHelper.LaunchProcess(testHostStartInfo.FileName, testHostStartInfo.Arguments, testHostStartInfo.WorkingDirectory, testHostStartInfo.EnvironmentVariables, this.ErrorReceivedCallback, this.ExitCallBack) as Process; } - catch (OperationCanceledException ex) + else { - EqtTrace.Error("DefaultTestHostManager.LaunchHost: Failed to launch testhost: {0}", ex); - this.messageLogger.SendMessage(TestMessageLevel.Error, ex.ToString()); - return false; + int processId = this.customTestHostLauncher.LaunchTestHost(testHostStartInfo, cancellationToken); + this.testHostProcess = Process.GetProcessById(processId); + this.processHelper.SetExitCallback(processId, this.ExitCallBack); } this.OnHostLaunched(new HostProviderEventArgs("Test Runtime launched", 0, this.testHostProcess.Id)); diff --git a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs index 295bb9934e..2f7150244d 100644 --- a/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs +++ b/src/Microsoft.TestPlatform.TestHostProvider/Hosting/DotnetTestHostManager.cs @@ -52,7 +52,7 @@ public class DotnetTestHostManager : ITestRuntimeProvider private IFileHelper fileHelper; - private ITestHostLauncher testHostLauncher; + private ITestHostLauncher customTestHostLauncher; private Process testHostProcess; @@ -144,7 +144,7 @@ public void Initialize(IMessageLogger logger, string runsettingsXml) /// public void SetCustomLauncher(ITestHostLauncher customLauncher) { - this.testHostLauncher = customLauncher; + this.customTestHostLauncher = customLauncher; } /// @@ -326,28 +326,19 @@ private void OnHostExited(HostProviderEventArgs e) private bool LaunchHost(TestProcessStartInfo testHostStartInfo, CancellationToken cancellationToken) { - try + this.testHostProcessStdError = new StringBuilder(this.ErrorLength, this.ErrorLength); + if (this.customTestHostLauncher == null) { - this.testHostProcessStdError = new StringBuilder(this.ErrorLength, this.ErrorLength); - if (this.testHostLauncher == null) - { - EqtTrace.Verbose("DotnetTestHostManager: Starting process '{0}' with command line '{1}'", testHostStartInfo.FileName, testHostStartInfo.Arguments); + EqtTrace.Verbose("DotnetTestHostManager: Starting process '{0}' with command line '{1}'", testHostStartInfo.FileName, testHostStartInfo.Arguments); - cancellationToken.ThrowIfCancellationRequested(); - this.testHostProcess = this.processHelper.LaunchProcess(testHostStartInfo.FileName, testHostStartInfo.Arguments, testHostStartInfo.WorkingDirectory, testHostStartInfo.EnvironmentVariables, this.ErrorReceivedCallback, this.ExitCallBack) as Process; - } - else - { - var processId = this.testHostLauncher.LaunchTestHost(testHostStartInfo); - this.testHostProcess = Process.GetProcessById(processId); - this.processHelper.SetExitCallback(processId, this.ExitCallBack); - } + cancellationToken.ThrowIfCancellationRequested(); + this.testHostProcess = this.processHelper.LaunchProcess(testHostStartInfo.FileName, testHostStartInfo.Arguments, testHostStartInfo.WorkingDirectory, testHostStartInfo.EnvironmentVariables, this.ErrorReceivedCallback, this.ExitCallBack) as Process; } - catch (OperationCanceledException ex) + else { - EqtTrace.Error("DotnetTestHostManager.LaunchHost: Failed to launch testhost: {0}", ex); - this.messageLogger.SendMessage(TestMessageLevel.Error, ex.ToString()); - return false; + var processId = this.customTestHostLauncher.LaunchTestHost(testHostStartInfo, cancellationToken); + this.testHostProcess = Process.GetProcessById(processId); + this.processHelper.SetExitCallback(processId, this.ExitCallBack); } this.OnHostLaunched(new HostProviderEventArgs("Test Runtime launched", 0, this.testHostProcess.Id)); diff --git a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs index 74837c6578..d589579782 100644 --- a/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs +++ b/src/vstest.console/TestPlatformHelpers/TestRequestManager.cs @@ -59,8 +59,6 @@ internal class TestRequestManager : ITestRequestManager /// private ITestRunRequest currentTestRunRequest; - private readonly EventWaitHandle runRequestStartedEventHandle = new AutoResetEvent(false); - private object syncobject = new object(); private Task metricsPublisher; @@ -295,8 +293,6 @@ public void RunTests(TestRunRequestPayload testRunRequestPayload, ITestHostLaunc public void CancelTestRun() { EqtTrace.Info("TestRequestManager.CancelTestRun: Sending cancel request."); - - this.runRequestStartedEventHandle.WaitOne(runRequestTimeout); this.currentTestRunRequest?.CancelAsync(); } @@ -306,8 +302,6 @@ public void CancelTestRun() public void AbortTestRun() { EqtTrace.Info("TestRequestManager.AbortTestRun: Sending abort request."); - - this.runRequestStartedEventHandle.WaitOne(runRequestTimeout); this.currentTestRunRequest?.Abort(); } @@ -517,8 +511,6 @@ private void RunTests(IRequestData requestData, TestRunCriteria testRunCriteria, this.testPlatformEventSource.ExecutionRequestStart(); this.currentTestRunRequest.ExecuteAsync(); - - this.runRequestStartedEventHandle.Set(); // Wait for the run completion event this.currentTestRunRequest.WaitForCompletion(); diff --git a/test/Microsoft.TestPlatform.AcceptanceTests/TranslationLayerTests/CustomTestHostLauncher.cs b/test/Microsoft.TestPlatform.AcceptanceTests/TranslationLayerTests/CustomTestHostLauncher.cs index 64da144d58..f96f9d7efa 100644 --- a/test/Microsoft.TestPlatform.AcceptanceTests/TranslationLayerTests/CustomTestHostLauncher.cs +++ b/test/Microsoft.TestPlatform.AcceptanceTests/TranslationLayerTests/CustomTestHostLauncher.cs @@ -4,7 +4,7 @@ namespace Microsoft.TestPlatform.AcceptanceTests.TranslationLayerTests { using System.Diagnostics; - + using System.Threading; using Microsoft.VisualStudio.TestPlatform.ObjectModel; using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client.Interfaces; @@ -19,11 +19,17 @@ public int ProcessId private set; } - /// public bool IsDebug => true; - /// public int LaunchTestHost(TestProcessStartInfo defaultTestHostStartInfo) + { + return this.LaunchTestHost(defaultTestHostStartInfo, CancellationToken.None); + } + + /// + public int LaunchTestHost(TestProcessStartInfo defaultTestHostStartInfo, CancellationToken cancellationToken) { var processInfo = new ProcessStartInfo( defaultTestHostStartInfo.FileName, diff --git a/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeClientTests.cs b/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeClientTests.cs index c2cb902ce5..264fd29bc6 100644 --- a/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeClientTests.cs +++ b/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeClientTests.cs @@ -285,7 +285,7 @@ public void DesignModeClientLaunchCustomHostMustReturnIfAckComes() Callback(() => Task.Run(sendMessageAction)); var info = new TestProcessStartInfo(); - var processId = testableDesignModeClient.LaunchCustomHost(info); + var processId = testableDesignModeClient.LaunchCustomHost(info, CancellationToken.None); Assert.AreEqual(expectedProcessId, processId); } @@ -309,7 +309,20 @@ public void DesignModeClientLaunchCustomHostMustThrowIfInvalidAckComes() .Callback(() => Task.Run(sendMessageAction)); var info = new TestProcessStartInfo(); - testableDesignModeClient.LaunchCustomHost(info); + testableDesignModeClient.LaunchCustomHost(info, CancellationToken.None); + } + + [TestMethod] + [ExpectedException(typeof(OperationCanceledException))] + public void DesignModeClientLaunchCustomHostMustThrowIfCancellationOccursBeforeHostLaunch() + { + var testableDesignModeClient = new TestableDesignModeClient(this.mockCommunicationManager.Object, JsonDataSerializer.Instance, this.mockPlatformEnvrironment.Object); + + var info = new TestProcessStartInfo(); + var cancellationTokenSource = new CancellationTokenSource(); + cancellationTokenSource.Cancel(); + + testableDesignModeClient.LaunchCustomHost(info, cancellationTokenSource.Token); } [TestMethod] diff --git a/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeTestHostLauncherTests.cs b/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeTestHostLauncherTests.cs index 6c86f33669..14d1df5c1e 100644 --- a/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeTestHostLauncherTests.cs +++ b/test/Microsoft.TestPlatform.Client.UnitTests/DesignMode/DesignModeTestHostLauncherTests.cs @@ -26,7 +26,7 @@ public void DesignModeTestHostLauncherLaunchTestHostShouldCallDesignModeClientTo launcher.LaunchTestHost(testProcessStartInfo); - mockDesignModeClient.Verify(md => md.LaunchCustomHost(testProcessStartInfo), Times.Once); + mockDesignModeClient.Verify(md => md.LaunchCustomHost(testProcessStartInfo, It.IsAny()), Times.Once); } [TestMethod] @@ -40,7 +40,7 @@ public void DesignModeDebugTestHostLauncherLaunchTestHostShouldCallDesignModeCli launcher.LaunchTestHost(testProcessStartInfo); - mockDesignModeClient.Verify(md => md.LaunchCustomHost(testProcessStartInfo), Times.Once); + mockDesignModeClient.Verify(md => md.LaunchCustomHost(testProcessStartInfo, It.IsAny()), Times.Once); } } } diff --git a/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionRequestSenderTests.cs b/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionRequestSenderTests.cs new file mode 100644 index 0000000000..b9e7ac208e --- /dev/null +++ b/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/DataCollectionRequestSenderTests.cs @@ -0,0 +1,62 @@ +// 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.TestPlatform.CommunicationUtilities.UnitTests +{ + using System; + using System.Collections.ObjectModel; + + using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; + using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.DataCollection; + using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; + using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.ObjectModel; + using Microsoft.VisualStudio.TestPlatform.ObjectModel; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + using Moq; + + [TestClass] + public class DataCollectionRequestSenderTests + { + private Mock mockCommunicationManager; + private DataCollectionRequestSender requestSender; + private Mock mockDataSerializer; + + public DataCollectionRequestSenderTests() + { + this.mockCommunicationManager = new Mock(); + this.mockDataSerializer = new Mock(); + this.requestSender = new DataCollectionRequestSender(this.mockCommunicationManager.Object, this.mockDataSerializer.Object); + } + + [TestMethod] + public void SendAfterTestRunStartAndGetResultShouldReturnAttachments() + { + var datacollectorUri = new Uri("my://custom/datacollector"); + var attachmentUri = new Uri("my://filename.txt"); + var displayName = "CustomDataCollector"; + var attachment = new AttachmentSet(datacollectorUri, displayName); + attachment.Attachments.Add(new UriDataAttachment(attachmentUri, "filename.txt")); + + this.mockDataSerializer.Setup(x => x.DeserializePayload>(It.IsAny())).Returns(new Collection() { attachment }); + this.mockCommunicationManager.Setup(x => x.ReceiveMessage()).Returns(new Message() { MessageType = MessageType.AfterTestRunEndResult, Payload = null }); + + var attachmentSets = this.requestSender.SendAfterTestRunStartAndGetResult(null, false); + + Assert.IsNotNull(attachmentSets); + Assert.AreEqual(attachmentSets.Count, 1); + Assert.IsNotNull(attachmentSets[0]); + Assert.AreEqual(attachmentSets[0].DisplayName, displayName); + Assert.AreEqual(datacollectorUri, attachmentSets[0].Uri); + Assert.AreEqual(attachmentUri, attachmentSets[0].Attachments[0].Uri); + } + + [TestMethod] + public void SendAfterTestRunStartAndGetResultShouldNotReturnAttachmentsWhenRequestCancelled() + { + var attachmentSets = this.requestSender.SendAfterTestRunStartAndGetResult(null, true); + + Assert.IsNull(attachmentSets); + } + } +} diff --git a/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/TestRequestSenderTests.cs b/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/TestRequestSenderTests.cs index 746d81e84a..9dad040c56 100644 --- a/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/TestRequestSenderTests.cs +++ b/test/Microsoft.TestPlatform.CommunicationUtilities.UnitTests/TestRequestSenderTests.cs @@ -80,11 +80,22 @@ public void WaitForRequestHandlerConnectionShouldWaitForClientToConnect() { this.SetupFakeCommunicationChannel(); - var connected = this.testRequestSender.WaitForRequestHandlerConnection(1); + var connected = this.testRequestSender.WaitForRequestHandlerConnection(1, It.IsAny()); Assert.IsTrue(connected); } + [TestMethod] + public void WaitForRequestHandlerConnectionWithInfiniteTimeoutShouldReturnImmediatelyWhenCancellationRequested() + { + var cancellationTokenSource = new CancellationTokenSource(); + cancellationTokenSource.Cancel(); + + var connected = this.testRequestSender.WaitForRequestHandlerConnection(-1, cancellationTokenSource.Token); + + Assert.IsFalse(connected); + } + [TestMethod] public void CloseShouldCallStopServerOnCommunicationManager() { diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs index 27aaf4f427..e460ac8fcf 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyDiscoveryManagerTests.cs @@ -62,7 +62,7 @@ public void DiscoverTestsShouldNotInitializeExtensionsOnNoExtensions() // Make sure TestPlugincache is refreshed. TestPluginCache.Instance = null; - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); this.testDiscoveryManager.DiscoverTests(this.discoveryCriteria, null); @@ -75,7 +75,7 @@ public void DiscoverTestsShouldNotInitializeExtensionsOnCommunicationFailure() // Make sure TestPlugincache is refreshed. TestPluginCache.Instance = null; - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); Mock mockTestDiscoveryEventHandler = new Mock(); @@ -91,7 +91,7 @@ public void DiscoverTestsShouldAllowRuntimeProviderToUpdateAdapterSource() TestPluginCache.Instance = null; this.mockTestHostManager.Setup(hm => hm.GetTestSources(this.discoveryCriteria.Sources)).Returns(this.discoveryCriteria.Sources); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); Mock mockTestDiscoveryEventHandler = new Mock(); @@ -111,7 +111,7 @@ public void DiscoverTestsShouldUpdateTestSourcesIfSourceDiffersFromTestHostManag this.mockTestHostManager.Setup(hm => hm.GetTestSources(localDiscoveryCriteria.Sources)).Returns(actualSources); this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(true)); this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new List()); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); Mock mockTestDiscoveryEventHandler = new Mock(); @@ -134,7 +134,7 @@ public void DiscoverTestsShouldNotUpdateTestSourcesIfSourceDoNotDifferFromTestHo this.mockTestHostManager.Setup(hm => hm.GetTestSources(localDiscoveryCriteria.Sources)).Returns(actualSources); this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(true)); this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new List()); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); Mock mockTestDiscoveryEventHandler = new Mock(); @@ -156,7 +156,7 @@ public void DiscoverTestsShouldNotSendDiscoveryRequestIfCommunicationFails() }) .Returns(Task.FromResult(false)); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); // Make sure TestPlugincache is refreshed. TestPluginCache.Instance = null; @@ -180,7 +180,7 @@ public void DiscoverTestsShouldInitializeExtensionsIfPresent() // Setup Mocks. TestPluginCacheTests.SetupMockAdditionalPathExtensions(extensions); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "c:\\e1.dll", "c:\\e2.dll" }); this.testDiscoveryManager.DiscoverTests(this.discoveryCriteria, null); @@ -201,7 +201,7 @@ public void DiscoverTestsShouldQueryTestHostManagerForExtensions() try { TestPluginCacheTests.SetupMockAdditionalPathExtensions(new[] { "c:\\e1.dll" }); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "he1.dll", "c:\\e1.dll" }); this.testDiscoveryManager.DiscoverTests(this.discoveryCriteria, null); @@ -222,7 +222,7 @@ public void DiscoverTestsShouldPassAdapterToTestHostManagerFromTestPluginCacheEx TestPluginCache.Instance.UpdateExtensions(new List { "abc.TestAdapter.dll", "xyz.TestAdapter.dll" }, false); try { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); var expectedResult = TestPluginCache.Instance.GetExtensionPaths(string.Empty); this.testDiscoveryManager.DiscoverTests(this.discoveryCriteria, null); @@ -251,7 +251,7 @@ public void DiscoverTestsShouldInitializeDefaultAdaptersIfSkipDefaultAdaptersIsF public void DiscoverTestsShouldNotIntializeTestHost() { // Setup mocks. - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); // Act. this.testDiscoveryManager.DiscoverTests(this.discoveryCriteria, null); @@ -350,7 +350,7 @@ public void DiscoverTestsShouldCatchExceptionAndCallHandleLogMessageOfError() public void DiscoverTestsShouldInitiateServerDiscoveryLoop() { // Setup mocks. - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); // Act. this.testDiscoveryManager.DiscoverTests(this.discoveryCriteria, null); @@ -469,7 +469,7 @@ private void InvokeAndVerifyDiscoverTests(bool skipDefaultAdapters) try { this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns((IEnumerable sources, IEnumerable extensions) => extensions); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); var expectedResult = TestPluginCache.Instance.GetExtensionPaths(TestPlatformConstants.TestAdapterEndsWithPattern, skipDefaultAdapters); this.testDiscoveryManager.Initialize(skipDefaultAdapters); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs index 3d0c6da61d..2c77a6a5d2 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerTests.cs @@ -61,7 +61,7 @@ public void StartTestRunShouldNotInitializeExtensionsOnNoExtensions() // Make sure TestPlugincache is refreshed. TestPluginCache.Instance = null; - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); this.testExecutionManager.StartTestRun(this.mockTestRunCriteria.Object, null); @@ -75,7 +75,7 @@ public void StartTestRunShouldAllowRuntimeProviderToUpdateAdapterSource() TestPluginCache.Instance = null; this.mockTestHostManager.Setup(hm => hm.GetTestSources(this.mockTestRunCriteria.Object.Sources)).Returns(this.mockTestRunCriteria.Object.Sources); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); Mock mockTestRunEventsHandler = new Mock(); @@ -97,7 +97,7 @@ public void StartTestRunShouldUpdateTestCaseSourceIfTestCaseSourceDiffersFromTes this.mockTestHostManager.Setup(hm => hm.GetTestSources(inputSource)).Returns(actualSources); this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(true)); this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new List()); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); Mock mockTestRunEventsHandler = new Mock(); this.testExecutionManager.StartTestRun(testRunCriteria, mockTestRunEventsHandler.Object); @@ -119,7 +119,7 @@ public void StartTestRunShouldNotUpdateTestCaseSourceIfTestCaseSourceDoNotDiffer this.mockTestHostManager.Setup(hm => hm.GetTestSources(inputSource)).Returns(actualSources); this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(true)); this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new List()); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); Mock mockTestRunEventsHandler = new Mock(); this.testExecutionManager.StartTestRun(testRunCriteria, mockTestRunEventsHandler.Object); @@ -134,7 +134,7 @@ public void StartTestRunShouldNotInitializeExtensionsOnCommunicationFailure() // Make sure TestPlugincache is refreshed. TestPluginCache.Instance = null; - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); Mock mockTestRunEventsHandler = new Mock(); @@ -152,7 +152,7 @@ public void StartTestRunShouldInitializeExtensionsIfPresent() try { var extensions = new List() { "C:\\foo.dll" }; - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); this.mockTestHostManager.Setup(x => x.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())) .Returns(extensions); @@ -173,7 +173,7 @@ public void StartTestRunShouldQueryTestHostManagerForExtensions() TestPluginCache.Instance = null; try { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "he1.dll", "c:\\e1.dll" }); this.testExecutionManager.StartTestRun(this.mockTestRunCriteria.Object, null); @@ -194,7 +194,7 @@ public void StartTestRunShouldPassAdapterToTestHostManagerFromTestPluginCacheExt TestPluginCache.Instance.UpdateExtensions(new List { "abc.TestAdapter.dll", "xyz.TestAdapter.dll" }, false); try { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); var expectedResult = TestPluginCache.Instance.GetExtensionPaths(string.Empty); this.testExecutionManager.StartTestRun(this.mockTestRunCriteria.Object, null); @@ -222,7 +222,7 @@ public void StartTestRunShouldInitializeDefaultAdaptersIfSkipDefaultAdaptersIsFa [TestMethod] public void StartTestRunShouldIntializeTestHost() { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); this.testExecutionManager.StartTestRun(this.mockTestRunCriteria.Object, null); @@ -241,7 +241,7 @@ public void StartTestRunShouldNotSendStartTestRunRequestIfCommunicationFails() }) .Returns(Task.FromResult(false)); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); // Make sure TestPlugincache is refreshed. TestPluginCache.Instance = null; @@ -258,7 +258,7 @@ public void StartTestRunShouldInitializeExtensionsIfTestHostIsNotShared() { TestPluginCache.Instance = null; this.mockTestHostManager.SetupGet(th => th.Shared).Returns(false); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns(new[] { "x.dll" }); this.testExecutionManager.StartTestRun(this.mockTestRunCriteria.Object, null); @@ -269,16 +269,16 @@ public void StartTestRunShouldInitializeExtensionsIfTestHostIsNotShared() [TestMethod] public void SetupChannelShouldThrowExceptionIfClientConnectionTimeout() { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(false)); - Assert.ThrowsException(() => this.testExecutionManager.SetupChannel(new List { "source.dll" }, CancellationToken.None)); + Assert.ThrowsException(() => this.testExecutionManager.SetupChannel(new List { "source.dll" })); } [TestMethod] public void StartTestRunShouldCatchExceptionAndCallHandleTestRunComplete() { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(false)); Mock mockTestRunEventsHandler = new Mock(); @@ -291,7 +291,7 @@ public void StartTestRunShouldCatchExceptionAndCallHandleTestRunComplete() [TestMethod] public void StartTestRunShouldCatchExceptionAndCallHandleRawMessageOfTestRunComplete() { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(false)); this.mockDataSerializer.Setup(ds => ds.SerializePayload(MessageType.TestMessage, It.IsAny())).Returns(MessageType.TestMessage); @@ -318,7 +318,7 @@ public void StartTestRunShouldCatchExceptionAndCallHandleRawMessageOfTestRunComp [TestMethod] public void StartTestRunShouldCatchExceptionAndCallHandleRawMessageOfTestMessage() { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(false)); this.mockDataSerializer.Setup(ds => ds.SerializePayload(MessageType.TestMessage, It.IsAny())).Returns(MessageType.TestMessage); @@ -345,7 +345,7 @@ public void StartTestRunShouldCatchExceptionAndCallHandleRawMessageOfTestMessage [TestMethod] public void StartTestRunShouldCatchExceptionAndCallHandleLogMessageOfError() { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(false)); Mock mockTestRunEventsHandler = new Mock(); @@ -358,7 +358,7 @@ public void StartTestRunShouldCatchExceptionAndCallHandleLogMessageOfError() [TestMethod] public void StartTestRunShouldCatchExceptionAndCallHandleRawMessageAndHandleLogMessage() { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny(), It.IsAny())).Returns(Task.FromResult(false)); Mock mockTestRunEventsHandler = new Mock(); @@ -373,7 +373,7 @@ public void StartTestRunShouldCatchExceptionAndCallHandleRawMessageAndHandleLogM public void StartTestRunShouldInitiateTestRunForSourcesThroughTheServer() { TestRunCriteriaWithSources testRunCriteriaPassed = null; - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); this.mockRequestSender.Setup(s => s.StartTestRun(It.IsAny(), this.testExecutionManager)) .Callback( (TestRunCriteriaWithSources criteria, ITestRunEventsHandler sink) => @@ -395,7 +395,7 @@ public void StartTestRunShouldInitiateTestRunForSourcesThroughTheServer() public void StartTestRunShouldInitiateTestRunForTestsThroughTheServer() { TestRunCriteriaWithTests testRunCriteriaPassed = null; - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); this.mockRequestSender.Setup(s => s.StartTestRun(It.IsAny(), this.testExecutionManager)) .Callback( (TestRunCriteriaWithTests criteria, ITestRunEventsHandler sink) => @@ -424,9 +424,9 @@ public void StartTestRunShouldInitiateTestRunForTestsThroughTheServer() [TestMethod] public void CloseShouldSignalToServerSessionEndIfTestHostWasLaunched() { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); - this.testExecutionManager.SetupChannel(new List { "source.dll" }, CancellationToken.None); + this.testExecutionManager.SetupChannel(new List { "source.dll" }); this.testExecutionManager.Close(); @@ -444,9 +444,9 @@ public void CloseShouldNotSendSignalToServerSessionEndIfTestHostWasNotLaunched() [TestMethod] public void CloseShouldSignalServerSessionEndEachTime() { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); - this.testExecutionManager.SetupChannel(new List { "source.dll" }, CancellationToken.None); + this.testExecutionManager.SetupChannel(new List { "source.dll" }); this.testExecutionManager.Close(); this.testExecutionManager.Close(); @@ -457,7 +457,7 @@ public void CloseShouldSignalServerSessionEndEachTime() [TestMethod] public void CancelShouldNotSendSendTestRunCancelIfCommunicationFails() { - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); Mock mockTestRunEventsHandler = new Mock(); @@ -468,12 +468,40 @@ public void CancelShouldNotSendSendTestRunCancelIfCommunicationFails() this.mockRequestSender.Verify(s => s.SendTestRunCancel(), Times.Never); } + [TestMethod] + public void AbortShouldSendTestRunAbortIfCommunicationSuccessful() + { + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); + + Mock mockTestRunEventsHandler = new Mock(); + + this.testExecutionManager.StartTestRun(this.mockTestRunCriteria.Object, mockTestRunEventsHandler.Object); + + this.testExecutionManager.Abort(It.IsAny()); + + this.mockRequestSender.Verify(s => s.SendTestRunAbort(), Times.Once); + } + + [TestMethod] + public void AbortShouldNotSendTestRunAbortIfCommunicationFails() + { + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); + + Mock mockTestRunEventsHandler = new Mock(); + + this.testExecutionManager.StartTestRun(this.mockTestRunCriteria.Object, mockTestRunEventsHandler.Object); + + this.testExecutionManager.Abort(It.IsAny()); + + this.mockRequestSender.Verify(s => s.SendTestRunAbort(), Times.Never); + } + [TestMethod] public void ExecuteTestsCloseTestHostIfRawMessageIfOfTypeExecutionComplete() { Mock mockTestRunEventsHandler = new Mock(); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); this.mockDataSerializer.Setup(ds => ds.SerializePayload(MessageType.TestMessage, It.IsAny())).Returns(MessageType.TestMessage); this.mockDataSerializer.Setup(ds => ds.SerializePayload(MessageType.ExecutionComplete, It.IsAny())).Returns(MessageType.ExecutionComplete); @@ -500,7 +528,7 @@ public void ExecuteTestsCloseTestHostIfRawMessageIfOfTypeExecutionComplete() public void ExecuteTestsShouldNotCloseTestHostIfRawMessageIsNotOfTypeExecutionComplete() { Mock mockTestRunEventsHandler = new Mock(); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); this.mockDataSerializer.Setup(mds => mds.DeserializeMessage(It.IsAny())).Returns(() => { @@ -569,7 +597,7 @@ public void ExecutionManagerShouldPassOnTestRunStatsChange() public void ExecutionManagerShouldPassOnHandleLogMessage() { Mock mockTestRunEventsHandler = new Mock(); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(false); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(false); this.mockDataSerializer.Setup(mds => mds.DeserializeMessage(It.IsAny())).Returns(() => { @@ -652,7 +680,7 @@ private void InvokeAndVerifyStartTestRun(bool skipDefaultAdapters) try { this.mockTestHostManager.Setup(th => th.GetTestPlatformExtensions(It.IsAny>(), It.IsAny>())).Returns((IEnumerable sources, IEnumerable extensions) => extensions); - this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny())).Returns(true); + this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny(), It.IsAny())).Returns(true); var expectedResult = TestPluginCache.Instance.GetExtensionPaths(TestPlatformConstants.TestAdapterEndsWithPattern, skipDefaultAdapters); this.testExecutionManager.Initialize(skipDefaultAdapters); diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerWithDataCollectionTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerWithDataCollectionTests.cs index f3a8aecadf..2141d28182 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerWithDataCollectionTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyExecutionManagerWithDataCollectionTests.cs @@ -107,25 +107,6 @@ public void InitializeShouldSaveExceptionMessagesIfThrownByDataCollectionProcess StringAssert.Contains(proxyExecutionManager.DataCollectionRunEventsHandler.Messages[0].Item2, "MyException"); } - [TestMethod] - public void CancelShouldInvokeAfterTestCaseEnd() - { - this.proxyExecutionManager.Cancel(It.IsAny()); - - this.mockDataCollectionManager.Verify(x => x.AfterTestRunEnd(true, It.IsAny()), Times.Once); - } - - [TestMethod] - public void CancelShouldThrowExceptionIfThrownByProxyDataCollectionManager() - { - this.mockDataCollectionManager.Setup(x => x.AfterTestRunEnd(true, It.IsAny())).Throws(); - - Assert.ThrowsException(() => - { - this.proxyExecutionManager.Cancel(It.IsAny()); - }); - } - [TestMethod] public void UpdateTestProcessStartInfoShouldUpdateDataCollectionPortArg() { diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs index 4e319f071e..e6457a5eae 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/Client/ProxyOperationManagerTests.cs @@ -55,7 +55,7 @@ public class ProxyOperationManagerTests : ProxyBaseManagerTests public ProxyOperationManagerTests() { this.mockRequestSender = new Mock(); - this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(connectionTimeout)).Returns(true); + this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(connectionTimeout, It.IsAny())).Returns(true); this.mockRequestData = new Mock(); this.mockRequestData.Setup(rd => rd.MetricsCollection).Returns(new Mock().Object); this.testOperationManager = new TestableProxyOperationManager(this.mockRequestData.Object, this.mockRequestSender.Object, this.mockTestHostManager.Object); @@ -76,7 +76,7 @@ public void SetupChannelShouldLaunchTestHost() th => th.GetTestHostProcessStartInfo(Enumerable.Empty(), null, It.IsAny())) .Returns(expectedStartInfo); - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.testOperationManager.SetupChannel(Enumerable.Empty()); this.mockTestHostManager.Verify(thl => thl.LaunchTestHostAsync(It.Is(si => si == expectedStartInfo), It.IsAny()), Times.Once); } @@ -87,7 +87,7 @@ public void SetupChannelShouldCreateTimestampedLogFileForHost() this.mockRequestSender.Setup(rs => rs.InitializeCommunication()).Returns(123); EqtTrace.InitializeVerboseTrace("log.txt"); - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.testOperationManager.SetupChannel(Enumerable.Empty()); this.mockTestHostManager.Verify( th => @@ -109,7 +109,7 @@ public void SetupChannelShouldAddRunnerProcessIdForTestHost() { this.mockRequestSender.Setup(rs => rs.InitializeCommunication()).Returns(123); - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.testOperationManager.SetupChannel(Enumerable.Empty()); this.mockTestHostManager.Verify( th => @@ -122,7 +122,7 @@ public void SetupChannelShouldAddRunnerProcessIdForTestHost() [TestMethod] public void SetupChannelShouldSetupServerForCommunication() { - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.testOperationManager.SetupChannel(Enumerable.Empty()); this.mockRequestSender.Verify(s => s.InitializeCommunication(), Times.Once); } @@ -149,7 +149,7 @@ public void SetupChannelShouldCallHostServerIfRunnerIsServer() var localTestOperationManager = new TestableProxyOperationManager(this.mockRequestData.Object, testRequestSender, this.mockTestHostManager.Object); - localTestOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + localTestOperationManager.SetupChannel(Enumerable.Empty()); mockCommunicationServer.Verify(s => s.Start(IPAddress.Loopback.ToString()+":0"), Times.Once); } @@ -180,7 +180,7 @@ public void SetupChannelShouldCallSetupClientIfRunnerIsClient() var localTestOperationManager = new TestableProxyOperationManager(this.mockRequestData.Object, testRequestSender, this.mockTestHostManager.Object); - localTestOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + localTestOperationManager.SetupChannel(Enumerable.Empty()); mockCommunicationEndpoint.Verify(s => s.Start(It.IsAny()), Times.Once); } @@ -188,8 +188,8 @@ public void SetupChannelShouldCallSetupClientIfRunnerIsClient() [TestMethod] public void SetupChannelShouldNotInitializeIfConnectionIsAlreadyInitialized() { - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.testOperationManager.SetupChannel(Enumerable.Empty()); + this.testOperationManager.SetupChannel(Enumerable.Empty()); this.mockRequestSender.Verify(s => s.InitializeCommunication(), Times.Once); } @@ -197,18 +197,18 @@ public void SetupChannelShouldNotInitializeIfConnectionIsAlreadyInitialized() [TestMethod] public void SetupChannelShouldWaitForTestHostConnection() { - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.testOperationManager.SetupChannel(Enumerable.Empty()); - this.mockRequestSender.Verify(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout), Times.Once); + this.mockRequestSender.Verify(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout, It.IsAny()), Times.Once); } [TestMethod] public void SetupChannelShouldNotWaitForTestHostConnectionIfConnectionIsInitialized() { - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.testOperationManager.SetupChannel(Enumerable.Empty()); + this.testOperationManager.SetupChannel(Enumerable.Empty()); - this.mockRequestSender.Verify(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout), Times.Exactly(1)); + this.mockRequestSender.Verify(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout, It.IsAny()), Times.Exactly(1)); } [TestMethod] @@ -216,40 +216,53 @@ public void SetupChannelShouldHonorTimeOutSetByUser() { Environment.SetEnvironmentVariable(EnvironmentHelper.VstestConnectionTimeout, "100"); - this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(100000)).Returns(true); - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(100000, It.IsAny())).Returns(true); + this.testOperationManager.SetupChannel(Enumerable.Empty()); - this.mockRequestSender.Verify(rs => rs.WaitForRequestHandlerConnection(100000), Times.Exactly(1)); + this.mockRequestSender.Verify(rs => rs.WaitForRequestHandlerConnection(100000, It.IsAny()), Times.Exactly(1)); } [TestMethod] public void SetupChannelShouldThrowIfWaitForTestHostConnectionTimesOut() { SetupTestHostLaunched(true); - this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout)).Returns(false); + this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout, It.IsAny())).Returns(false); var operationManager = new TestableProxyOperationManager(this.mockRequestData.Object, this.mockRequestSender.Object, this.mockTestHostManager.Object); - var message = Assert.ThrowsException(() => operationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None)).Message; + var message = Assert.ThrowsException(() => operationManager.SetupChannel(Enumerable.Empty())).Message; Assert.AreEqual(message, ProxyOperationManagerTests.TimoutErrorMessage); } + [TestMethod] + public void SetupChannelShouldThrowIfRequestCancelled() + { + SetupTestHostLaunched(true); + this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout, It.IsAny())).Returns(false); + + var cancellationTokenSource = new CancellationTokenSource(); + var operationManager = new TestableProxyOperationManager(this.mockRequestData.Object, this.mockRequestSender.Object, this.mockTestHostManager.Object, cancellationTokenSource); + + cancellationTokenSource.Cancel(); + Assert.ThrowsException(() => operationManager.SetupChannel(Enumerable.Empty())); + } + [TestMethod] public void SetupChannelShouldThrowIfLaunchTestHostFails() { SetupTestHostLaunched(false); - this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout)).Returns(true); + this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout, It.IsAny())).Returns(true); var operationManager = new TestableProxyOperationManager(this.mockRequestData.Object, this.mockRequestSender.Object, this.mockTestHostManager.Object); - - var message = Assert.ThrowsException(() => operationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None)).Message; + + var message = Assert.ThrowsException(() => operationManager.SetupChannel(Enumerable.Empty())).Message; Assert.AreEqual(message, string.Format(CultureInfo.CurrentUICulture, Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources.InitializationFailed)); } [TestMethod] public void SetupChannelShouldCheckVersionWithTestHost() { - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.testOperationManager.SetupChannel(Enumerable.Empty()); this.mockRequestSender.Verify(rs => rs.CheckVersionWithTestHost(), Times.Once); } @@ -258,7 +271,7 @@ public void SetupChannelShouldThrowExceptionIfVersionCheckFails() { // Make the version check fail this.mockRequestSender.Setup(rs => rs.CheckVersionWithTestHost()).Throws(new TestPlatformException("Version check failed")); - Assert.ThrowsException(() => this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None)); + Assert.ThrowsException(() => this.testOperationManager.SetupChannel(Enumerable.Empty())); } [TestMethod] @@ -268,7 +281,7 @@ public void SetupChannelForDotnetHostManagerWithIsVersionCheckRequiredFalseShoul var testHostManager = new TestableDotnetTestHostManager(false, this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockEnvironment.Object); var operationManager = new TestableProxyOperationManager(this.mockRequestData.Object, this.mockRequestSender.Object, testHostManager); - operationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + operationManager.SetupChannel(Enumerable.Empty()); this.mockRequestSender.Verify(rs => rs.CheckVersionWithTestHost(), Times.Never); } @@ -280,7 +293,7 @@ public void SetupChannelForDotnetHostManagerWithIsVersionCheckRequiredTrueShould var testHostManager = new TestableDotnetTestHostManager(true, this.mockProcessHelper.Object, this.mockFileHelper.Object, this.mockEnvironment.Object); var operationManager = new TestableProxyOperationManager(this.mockRequestData.Object, this.mockRequestSender.Object, testHostManager); - operationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + operationManager.SetupChannel(Enumerable.Empty()); this.mockRequestSender.Verify(rs => rs.CheckVersionWithTestHost(), Times.Once); } @@ -288,8 +301,8 @@ public void SetupChannelForDotnetHostManagerWithIsVersionCheckRequiredTrueShould [TestMethod] public void CloseShouldEndSessionIfHostWasLaunched() { - this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout)).Returns(true); - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout, It.IsAny())).Returns(true); + this.testOperationManager.SetupChannel(Enumerable.Empty()); this.testOperationManager.Close(); @@ -316,12 +329,12 @@ public void CloseShouldAlwaysCleanTestHost() public void CloseShouldResetChannelInitialization() { this.SetupWaitForTestHostExit(); - this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout)).Returns(true); - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout, It.IsAny())).Returns(true); + this.testOperationManager.SetupChannel(Enumerable.Empty()); this.testOperationManager.Close(); - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.testOperationManager.SetupChannel(Enumerable.Empty()); this.mockTestHostManager.Verify(th => th.LaunchTestHostAsync(It.IsAny(), It.IsAny()), Times.Exactly(2)); } @@ -329,12 +342,12 @@ public void CloseShouldResetChannelInitialization() public void CloseShouldTerminateTesthostProcessIfWaitTimesout() { // Ensure testhost start returns a dummy process id - this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout)).Returns(true); - this.testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + this.mockRequestSender.Setup(rs => rs.WaitForRequestHandlerConnection(this.connectionTimeout, It.IsAny())).Returns(true); + this.testOperationManager.SetupChannel(Enumerable.Empty()); this.testOperationManager.Close(); - this.mockTestHostManager.Verify(th => th.CleanTestHostAsync(CancellationToken.None), Times.Once); + this.mockTestHostManager.Verify(th => th.CleanTestHostAsync(It.IsAny()), Times.Once); } [TestMethod] @@ -380,7 +393,7 @@ public void UpdateTestProcessStartInfoShouldUpdateTelemetryOptedInArgTrueIfTelem .Returns(Task.FromResult(true)); // Act. - testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + testOperationManager.SetupChannel(Enumerable.Empty()); // Verify. Assert.IsTrue(receivedTestProcessInfo.Arguments.Contains("--telemetryoptedin true")); @@ -406,7 +419,7 @@ public void UpdateTestProcessStartInfoShouldUpdateTelemetryOptedInArgFalseIfTele .Returns(Task.FromResult(true)); // Act. - testOperationManager.SetupChannel(Enumerable.Empty(), CancellationToken.None); + testOperationManager.SetupChannel(Enumerable.Empty()); // Verify. Assert.IsTrue(receivedTestProcessInfo.Arguments.Contains("--telemetryoptedin false")); @@ -437,19 +450,6 @@ private void SetUpMocksForDotNetTestHost() }).Returns(Process.GetCurrentProcess()); } - //private void SetupChannelMessage(string messageType, string returnMessageType, TPayload returnPayload) - //{ - // this.mockChannel.Setup(mc => mc.Send(It.Is(s => s.Contains(messageType)))) - // .Callback(() => this.mockChannel.Raise(c => c.MessageReceived += null, this.mockChannel.Object, new MessageReceivedEventArgs { Data = messageType })); - - // this.mockDataSerializer.Setup(ds => ds.SerializePayload(It.Is(s => s.Equals(messageType)), It.IsAny())).Returns(messageType); - // this.mockDataSerializer.Setup(ds => ds.SerializePayload(It.Is(s => s.Equals(messageType)), It.IsAny(), It.IsAny())).Returns(messageType); - // this.mockDataSerializer.Setup(ds => ds.DeserializeMessage(It.Is(s => s.Equals(messageType)))) - // .Returns(new Message { MessageType = returnMessageType }); - // this.mockDataSerializer.Setup(ds => ds.DeserializePayload(It.Is(m => m.MessageType.Equals(messageType)))) - // .Returns(returnPayload); - //} - private class TestableProxyOperationManager : ProxyOperationManager { public TestableProxyOperationManager(IRequestData requestData, @@ -457,6 +457,15 @@ public TestableProxyOperationManager(IRequestData requestData, ITestRuntimeProvider testHostManager) : base(requestData, requestSender, testHostManager) { } + + public TestableProxyOperationManager( + IRequestData requestData, + ITestRequestSender requestSender, + ITestRuntimeProvider testHostManager, + CancellationTokenSource cancellationTokenSource) : base(requestData, requestSender, testHostManager) + { + this.CancellationTokenSource = cancellationTokenSource; + } } private class TestableDotnetTestHostManager : DotnetTestHostManager diff --git a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DataCollectionTestRunEventsHandlerTests.cs b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DataCollectionTestRunEventsHandlerTests.cs index c64c23d2b2..9335de51be 100644 --- a/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DataCollectionTestRunEventsHandlerTests.cs +++ b/test/Microsoft.TestPlatform.CrossPlatEngine.UnitTests/DataCollection/DataCollectionTestRunEventsHandlerTests.cs @@ -6,7 +6,7 @@ namespace TestPlatform.CommunicationUtilities.UnitTests.ObjectModel using System; using System.Collections.ObjectModel; using System.Linq; - + using System.Threading; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Interfaces; using Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.ObjectModel; @@ -33,7 +33,7 @@ public void InitializeTests() this.baseTestRunEventsHandler = new Mock(); this.proxyDataCollectionManager = new Mock(); this.mockDataSerializer = new Mock(); - this.testRunEventHandler = new DataCollectionTestRunEventsHandler(this.baseTestRunEventsHandler.Object, this.proxyDataCollectionManager.Object, this.mockDataSerializer.Object); + this.testRunEventHandler = new DataCollectionTestRunEventsHandler(this.baseTestRunEventsHandler.Object, this.proxyDataCollectionManager.Object, CancellationToken.None, this.mockDataSerializer.Object); } [TestMethod] @@ -66,6 +66,45 @@ public void HandleRawMessageShouldGetDataCollectorAttachments() Times.Once); } + [TestMethod] + public void HandleRawMessageShouldInvokeAfterTestRunEndPassingFalseIfRequestNotCancelled() + { + var testRunCompleteEventArgs = new TestRunCompleteEventArgs(null, false, false, null, new Collection(), new TimeSpan()); + + this.mockDataSerializer.Setup(x => x.DeserializeMessage(It.IsAny())).Returns(new Message() { MessageType = MessageType.ExecutionComplete }); + this.mockDataSerializer.Setup(x => x.DeserializePayload(It.IsAny())) + .Returns(new TestRunCompletePayload() { TestRunCompleteArgs = testRunCompleteEventArgs }); + + var cancellationTokenSource = new CancellationTokenSource(); + testRunEventHandler = new DataCollectionTestRunEventsHandler(this.baseTestRunEventsHandler.Object, this.proxyDataCollectionManager.Object, cancellationTokenSource.Token, this.mockDataSerializer.Object); + + testRunEventHandler.HandleRawMessage(string.Empty); + + this.proxyDataCollectionManager.Verify( + dcm => dcm.AfterTestRunEnd(false, It.IsAny()), + Times.Once); + } + + [TestMethod] + public void HandleRawMessageShouldInvokeAfterTestRunEndPassingTrueIfRequestCancelled() + { + var testRunCompleteEventArgs = new TestRunCompleteEventArgs(null, false, false, null, new Collection(), new TimeSpan()); + + this.mockDataSerializer.Setup(x => x.DeserializeMessage(It.IsAny())).Returns(new Message() { MessageType = MessageType.ExecutionComplete }); + this.mockDataSerializer.Setup(x => x.DeserializePayload(It.IsAny())) + .Returns(new TestRunCompletePayload() { TestRunCompleteArgs = testRunCompleteEventArgs }); + + var cancellationTokenSource = new CancellationTokenSource(); + testRunEventHandler = new DataCollectionTestRunEventsHandler(this.baseTestRunEventsHandler.Object, this.proxyDataCollectionManager.Object, cancellationTokenSource.Token, this.mockDataSerializer.Object); + cancellationTokenSource.Cancel(); + + testRunEventHandler.HandleRawMessage(string.Empty); + + this.proxyDataCollectionManager.Verify( + dcm => dcm.AfterTestRunEnd(true, It.IsAny()), + Times.Once); + } + #region Get Combined Attachments [TestMethod] public void GetCombinedAttachmentSetsShouldReturnCombinedAttachments() diff --git a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs index bffb9f85bc..578e0f706d 100644 --- a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs +++ b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DefaultTestHostManagerTests.cs @@ -368,13 +368,13 @@ public void LaunchTestHostShouldUseCustomHostIfSet() var mockCustomLauncher = new Mock(); this.testHostManager.SetCustomLauncher(mockCustomLauncher.Object); var currentProcess = Process.GetCurrentProcess(); - mockCustomLauncher.Setup(mc => mc.LaunchTestHost(It.IsAny())).Returns(currentProcess.Id); + mockCustomLauncher.Setup(mc => mc.LaunchTestHost(It.IsAny(), It.IsAny())).Returns(currentProcess.Id); this.testHostManager.HostLaunched += this.TestHostManagerHostLaunched; Task pid = this.testHostManager.LaunchTestHostAsync(this.startInfo, CancellationToken.None); pid.Wait(); - mockCustomLauncher.Verify(mc => mc.LaunchTestHost(It.IsAny()), Times.Once); + mockCustomLauncher.Verify(mc => mc.LaunchTestHost(It.IsAny(), It.IsAny()), Times.Once); Assert.IsTrue(pid.Result); Assert.AreEqual(currentProcess.Id, this.testHostId); @@ -386,7 +386,7 @@ public void LaunchTestHostShouldSetExitCallbackInCaseCustomHost() var mockCustomLauncher = new Mock(); this.testHostManager.SetCustomLauncher(mockCustomLauncher.Object); var currentProcess = Process.GetCurrentProcess(); - mockCustomLauncher.Setup(mc => mc.LaunchTestHost(It.IsAny())).Returns(currentProcess.Id); + mockCustomLauncher.Setup(mc => mc.LaunchTestHost(It.IsAny(), It.IsAny())).Returns(currentProcess.Id); this.testHostManager.LaunchTestHostAsync(this.startInfo, CancellationToken.None).Wait(); this.mockProcessHelper.Verify(ph => ph.SetExitCallback(currentProcess.Id, It.IsAny>())); diff --git a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs index 409e683868..285dcda804 100644 --- a/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs +++ b/test/Microsoft.TestPlatform.TestHostProvider.UnitTests/Hosting/DotnetTestHostManagerTests.cs @@ -211,7 +211,7 @@ public void GetTestHostProcessStartInfoShouldIncludeEnvironmentVariables() public void LaunchTestHostShouldLaunchProcessWithNullEnvironmentVariablesOrArgs() { var expectedProcessId = Process.GetCurrentProcess().Id; - this.mockTestHostLauncher.Setup(thl => thl.LaunchTestHost(It.IsAny())).Returns(expectedProcessId); + this.mockTestHostLauncher.Setup(thl => thl.LaunchTestHost(It.IsAny(), It.IsAny())).Returns(expectedProcessId); this.mockFileHelper.Setup(ph => ph.Exists("testhost.dll")).Returns(true); var startInfo = this.GetDefaultStartInfo(); this.dotnetHostManager.SetCustomLauncher(this.mockTestHostLauncher.Object); @@ -252,7 +252,7 @@ public void LaunchTestHostShouldLaunchProcessWithEnvironmentVariables() processId.Wait(); Assert.IsTrue(processId.Result); - this.mockTestHostLauncher.Verify(thl => thl.LaunchTestHost(It.Is(x => x.EnvironmentVariables.Equals(variables))), Times.Once); + this.mockTestHostLauncher.Verify(thl => thl.LaunchTestHost(It.Is(x => x.EnvironmentVariables.Equals(variables)), It.IsAny()), Times.Once); } [TestMethod] @@ -366,14 +366,14 @@ public async Task LaunchTestHostShouldLaunchProcessWithConnectionInfo() this.dotnetHostManager.SetCustomLauncher(this.mockTestHostLauncher.Object); await this.dotnetHostManager.LaunchTestHostAsync(this.defaultTestProcessStartInfo, CancellationToken.None); - this.mockTestHostLauncher.Verify(thl => thl.LaunchTestHost(It.Is(x => x.Arguments.Equals(expectedArgs))), Times.Once); + this.mockTestHostLauncher.Verify(thl => thl.LaunchTestHost(It.Is(x => x.Arguments.Equals(expectedArgs)), It.IsAny()), Times.Once); } [TestMethod] public void LaunchTestHostShouldSetExitCallBackInCaseCustomHost() { var expectedProcessId = Process.GetCurrentProcess().Id; - this.mockTestHostLauncher.Setup(thl => thl.LaunchTestHost(It.IsAny())).Returns(expectedProcessId); + this.mockTestHostLauncher.Setup(thl => thl.LaunchTestHost(It.IsAny(), It.IsAny())).Returns(expectedProcessId); this.mockFileHelper.Setup(ph => ph.Exists("testhost.dll")).Returns(true); var startInfo = this.GetDefaultStartInfo(); diff --git a/test/vstest.console.UnitTests/TestPlatformHelpers/TestRequestManagerTests.cs b/test/vstest.console.UnitTests/TestPlatformHelpers/TestRequestManagerTests.cs index e535e4eb1d..a986fd330e 100644 --- a/test/vstest.console.UnitTests/TestPlatformHelpers/TestRequestManagerTests.cs +++ b/test/vstest.console.UnitTests/TestPlatformHelpers/TestRequestManagerTests.cs @@ -814,44 +814,6 @@ public void DiscoverTestsShouldPublishMetrics() this.mockMetricsPublisher.Verify(mp => mp.PublishMetrics(TelemetryDataConstants.TestDiscoveryCompleteEvent, It.IsAny>()), Times.Once); } - [TestMethod] - public void CancelTestRunShouldWaitForCreateTestRunRequest() - { - var payload = new TestRunRequestPayload() - { - Sources = new List() { "a", "b" }, - RunSettings = DefaultRunsettings - }; - - bool createTestRunRequestCalled = false; - bool cancelCalledPostTestRunRequest = false; - - var mockRunRequest = new Mock(); - this.mockTestPlatform.Setup(mt => mt.CreateTestRunRequest(It.IsAny(), It.IsAny(), It.IsAny())).Callback( - (IRequestData requestData, TestRunCriteria testRunCriteria, TestPlatformOptions options) => - { - createTestRunRequestCalled = true; - }).Returns(mockRunRequest.Object); - - // Run request should not complete before the abort - mockRunRequest.Setup(mr => mr.WaitForCompletion(It.IsAny())).Callback(() => { Thread.Sleep(20); }); - - mockRunRequest.Setup(mr => mr.CancelAsync()).Callback(() => - { - cancelCalledPostTestRunRequest = createTestRunRequestCalled; - }); - - var mockRunEventsRegistrar = new Mock(); - var mockCustomlauncher = new Mock(); - - var cancelTask = Task.Run(() => this.testRequestManager.CancelTestRun()); - var runTask = Task.Run(() => this.testRequestManager.RunTests(payload, mockCustomlauncher.Object, mockRunEventsRegistrar.Object, this.protocolConfig)); - - Task.WaitAll(cancelTask, runTask); - - Assert.IsTrue(cancelCalledPostTestRunRequest, "CancelRequest must execute after create run request"); - } - [TestMethod] public void CancelShouldNotThrowExceptionIfTestRunRequestHasBeenDisposed() { @@ -884,44 +846,6 @@ public void AbortShouldNotThrowExceptionIfTestRunRequestHasBeenDisposed() this.testRequestManager.AbortTestRun(); } - [TestMethod] - public void AbortTestRunShouldWaitForCreateTestRunRequest() - { - var payload = new TestRunRequestPayload() - { - Sources = new List() { "a", "b" }, - RunSettings = DefaultRunsettings - }; - - bool createTestRunRequestCalled = false; - bool abortCalledPostTestRunRequest = false; - - var mockRunRequest = new Mock(); - this.mockTestPlatform.Setup(mt => mt.CreateTestRunRequest(It.IsAny(), It.IsAny(), It.IsAny())).Callback( - (IRequestData requestData, TestRunCriteria testRunCriteria, TestPlatformOptions options) => - { - createTestRunRequestCalled = true; - }).Returns(mockRunRequest.Object); - - // Run request should not complete before the abort - mockRunRequest.Setup(mr => mr.WaitForCompletion(It.IsAny())).Callback(() => { Thread.Sleep(20); }); - - mockRunRequest.Setup(mr => mr.Abort()).Callback(() => - { - abortCalledPostTestRunRequest = createTestRunRequestCalled; - }); - - var mockRunEventsRegistrar = new Mock(); - var mockCustomlauncher = new Mock(); - - var cancelTask = Task.Run(() => this.testRequestManager.AbortTestRun()); - var runTask = Task.Run(() => this.testRequestManager.RunTests(payload, mockCustomlauncher.Object, mockRunEventsRegistrar.Object, this.protocolConfig)); - - Task.WaitAll(cancelTask, runTask); - - Assert.IsTrue(abortCalledPostTestRunRequest, "Abort Request must execute after create run request"); - } - [TestMethod] public void RunTestsShouldReadTheBatchSizeFromSettingsAndSetItForTestRunCriteria() {