Skip to content

Commit

Permalink
Run NetFramework tests inside vstest.console.exe process (#1009)
Browse files Browse the repository at this point in the history
* No isolation discovery for net46 with design mode off

* NoIsolation test run for net46

* Make api asynchronous

* 1) Renamed argument processor to InProcess
2) Wrote unit tests.

* 1) Making in process default for net46
2) Enable InIsolation argument to disable default in process.
3) Address PR comment

* Disable inprocess for inProcDataCollector.

* Addressed Arun comment

* Append comment
  • Loading branch information
Faizan2304 authored Aug 28, 2017
1 parent 722818c commit f205078
Show file tree
Hide file tree
Showing 34 changed files with 1,089 additions and 96 deletions.
1 change: 1 addition & 0 deletions src/Microsoft.TestPlatform.Client/TestPlatform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ static TestPlatform()
/// <summary>
/// Initializes a new instance of the <see cref="TestPlatform"/> class.
/// </summary>
/// <param name="isInIsolation">inIsolation command line arg value</param>
public TestPlatform() : this(new TestEngine(), new FileHelper(), TestRuntimeProviderManager.Instance)
{
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;

internal class InProcessProxyDiscoveryManager : IProxyDiscoveryManager
{
private ITestHostManagerFactory testHostManagerFactory;
private IDiscoveryManager discoveryManager;
private ITestRuntimeProvider testHostManager;
public bool IsInitialized { get; private set; } = false;

/// <summary>
/// Initializes a new instance of the <see cref="InProcessProxyDiscoveryManager"/> class.
/// </summary>
public InProcessProxyDiscoveryManager(ITestRuntimeProvider testHostManager) : this(testHostManager, new TestHostManagerFactory())
{
}

/// <summary>
/// Initializes a new instance of the <see cref="InProcessProxyDiscoveryManager"/> class.
/// </summary>
/// <param name="testHostManagerFactory">Manager factory</param>
internal InProcessProxyDiscoveryManager(ITestRuntimeProvider testHostManager, ITestHostManagerFactory testHostManagerFactory)
{
this.testHostManager = testHostManager;
this.testHostManagerFactory = testHostManagerFactory;
this.discoveryManager = this.testHostManagerFactory.GetDiscoveryManager();
}

/// <summary>
/// Initializes test discovery.
/// </summary>
public void Initialize()
{
}

/// <summary>
/// Discovers tests
/// </summary>
/// <param name="discoveryCriteria">Settings, parameters for the discovery request</param>
/// <param name="eventHandler">EventHandler for handling discovery events from Engine</param>
public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEventsHandler eventHandler)
{
Task.Run(() =>
{
try
{
// Initialize extension before discovery
this.InitializeExtensions(discoveryCriteria.Sources);
this.discoveryManager.DiscoverTests(discoveryCriteria, eventHandler);
}
catch (Exception exception)
{
EqtTrace.Error("InProcessProxyDiscoveryManager.DiscoverTests: Failed to discover tests: {0}", exception);
// Send a discovery complete to caller.
eventHandler.HandleLogMessage(TestMessageLevel.Error, exception.ToString());
eventHandler.HandleDiscoveryComplete(-1, Enumerable.Empty<TestCase>(), true);
}
}
);
}

/// <summary>
/// Closes the current test operation.
/// This function is of no use in this context as we are not creating any testhost
/// </summary>
public void Close()
{
}

/// <summary>
/// Aborts the test operation.
/// </summary>
public void Abort()
{
Task.Run(() => this.testHostManagerFactory.GetDiscoveryManager().Abort());
}

private void InitializeExtensions(IEnumerable<string> sources)
{
var extensionsFromSource = this.testHostManager.GetTestPlatformExtensions(sources, Enumerable.Empty<string>());
if (extensionsFromSource.Any())
{
TestPluginCache.Instance.UpdateExtensions(extensionsFromSource, false);
}

// We don't need to pass list of extension as we are running inside vstest.console and
// it will use TestPluginCache of vstest.console
discoveryManager.Initialize(Enumerable.Empty<string>());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;

internal class InProcessProxyExecutionManager : IProxyExecutionManager
{
private ITestHostManagerFactory testHostManagerFactory;
private IExecutionManager executionManager;
private ITestRuntimeProvider testHostManager;
public bool IsInitialized { get; private set; } = false;

/// <summary>
/// Initializes a new instance of the <see cref="InProcessProxyexecutionManager"/> class.
/// </summary>
public InProcessProxyExecutionManager(ITestRuntimeProvider testHostManager) : this(testHostManager, new TestHostManagerFactory())
{
}

/// <summary>
/// Initializes a new instance of the <see cref="InProcessProxyexecutionManager"/> class.
/// </summary>
/// <param name="testHostManagerFactory">
/// Manager factory
/// </param>
internal InProcessProxyExecutionManager(ITestRuntimeProvider testHostManager, ITestHostManagerFactory testHostManagerFactory)
{
this.testHostManager = testHostManager;
this.testHostManagerFactory = testHostManagerFactory;
this.executionManager = this.testHostManagerFactory.GetExecutionManager();
}

/// <summary>
/// Initialize adapters.
/// </summary>
public void Initialize()
{
}

/// <inheritdoc/>
public int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEventsHandler eventHandler)
{
try
{
// This code should be in sync with ProxyExecutionManager.StartTestRun executionContext
var executionContext = new TestExecutionContext(
testRunCriteria.FrequencyOfRunStatsChangeEvent,
testRunCriteria.RunStatsChangeEventTimeout,
inIsolation: false,
keepAlive: testRunCriteria.KeepAlive,
isDataCollectionEnabled: false,
areTestCaseLevelEventsRequired: false,
hasTestRun: true,
isDebug: (testRunCriteria.TestHostLauncher != null && testRunCriteria.TestHostLauncher.IsDebug),
testCaseFilter: testRunCriteria.TestCaseFilter);


if (testRunCriteria.HasSpecificSources)
{
// Initialize extension before execution
this.InitializeExtensions(testRunCriteria.Sources);

Task.Run(() => executionManager.StartTestRun(testRunCriteria.AdapterSourceMap, testRunCriteria.TestRunSettings, executionContext, null, eventHandler));
}
else
{
// If the test execution is with a test filter, group them by sources
var testSources = testRunCriteria.Tests.GroupBy(tc => tc.Source).Select(g => g.Key);

// Initialize extension before execution
this.InitializeExtensions(testSources);

Task.Run(() => executionManager.StartTestRun(testRunCriteria.Tests, testRunCriteria.TestRunSettings, executionContext, null, eventHandler));
}
}
catch (Exception exception)
{
EqtTrace.Error("InProcessProxyexecutionManager.StartTestRun: Failed to start test run: {0}", exception);

// Send exception message.
eventHandler.HandleLogMessage(TestMessageLevel.Error, exception.ToString());

// Send a run complete to caller.
var completeArgs = new TestRunCompleteEventArgs(null, false, true, exception, new Collection<AttachmentSet>(), TimeSpan.Zero);
eventHandler.HandleTestRunComplete(completeArgs, null, null, null);
}

return 0;
}

/// <summary>
/// Aborts the test operation.
/// </summary>
public void Abort()
{
Task.Run(() => this.testHostManagerFactory.GetExecutionManager().Abort());
}

/// <summary>
/// Cancels the test run.
/// </summary>
public void Cancel()
{
Task.Run(() => this.testHostManagerFactory.GetExecutionManager().Cancel());
}

/// <summary>
/// Closes the current test operation.
/// This function is of no use in this context as we are not creating any testhost
/// </summary>
public void Close()
{
}


private void InitializeExtensions(IEnumerable<string> sources)
{
var extensionsFromSource = this.testHostManager.GetTestPlatformExtensions(sources, Enumerable.Empty<string>());
if (extensionsFromSource.Any())
{
TestPluginCache.Instance.UpdateExtensions(extensionsFromSource, false);
}

// We don't need to pass list of extension as we are running inside vstest.console and
// it will use TestPluginCache of vstest.console
executionManager.Initialize(Enumerable.Empty<string>());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public virtual int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEventsH

this.InitializeExtensions(testSources);

// This code should be in sync with InProcessProxyExecutionManager.StartTestRun executionContext
var executionContext = new TestExecutionContext(
testRunCriteria.FrequencyOfRunStatsChangeEvent,
testRunCriteria.RunStatsChangeEventTimeout,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,11 @@ public void Initialize(IEnumerable<string> pathToAdditionalExtensions)
{
this.testPlatformEventSource.AdapterSearchStart();

// Start using these additional extensions
TestPluginCache.Instance.DefaultExtensionPaths = pathToAdditionalExtensions;
if (pathToAdditionalExtensions != null && pathToAdditionalExtensions.Any())
{
// Start using these additional extensions
TestPluginCache.Instance.DefaultExtensionPaths = pathToAdditionalExtensions;
}

// Load and Initialize extensions.
TestDiscoveryExtensionManager.LoadAndInitializeAllExtensions(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Execution
{
using System;
using System.Collections.Generic;

using System.Linq;
using Microsoft.VisualStudio.TestPlatform.Common.ExtensionFramework;
using Microsoft.VisualStudio.TestPlatform.Common.SettingsProvider;
using Microsoft.VisualStudio.TestPlatform.CoreUtilities.Tracing;
Expand Down Expand Up @@ -53,8 +53,12 @@ public void Initialize(IEnumerable<string> pathToAdditionalExtensions)
{
this.testPlatformEventSource.AdapterSearchStart();

// Start using these additional extensions
TestPluginCache.Instance.DefaultExtensionPaths = pathToAdditionalExtensions;
if (pathToAdditionalExtensions != null && pathToAdditionalExtensions.Any())
{
// Start using these additional extensions
TestPluginCache.Instance.DefaultExtensionPaths = pathToAdditionalExtensions;
}

this.LoadExtensions();

this.testPlatformEventSource.AdapterSearchStop();
Expand Down
Loading

0 comments on commit f205078

Please sign in to comment.