-
Notifications
You must be signed in to change notification settings - Fork 319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Run NetFramework tests inside vstest.console.exe process #1009
Changes from 1 commit
e98195a
ddb91be
bfb18d6
a881a1a
a2a391d
ede0e04
2f76f3c
d1237cd
172f9d0
39c40c2
ed5a9ca
4124fde
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
2) Enable InIsolation argument to disable default in process. 3) Address PR comment
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,9 +13,10 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client | |
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol; | ||
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; | ||
|
||
class InProcessProxyDiscoveryManager : IProxyDiscoveryManager | ||
internal class InProcessProxyDiscoveryManager : IProxyDiscoveryManager | ||
{ | ||
private ITestHostManagerFactory testHostManagerFactory; | ||
IDiscoveryManager discoveryManager; | ||
public bool IsInitialized { get; private set; } = false; | ||
|
||
/// <summary> | ||
|
@@ -32,6 +33,7 @@ public InProcessProxyDiscoveryManager() : this(new TestHostManagerFactory()) | |
internal InProcessProxyDiscoveryManager(ITestHostManagerFactory testHostManagerFactory) | ||
{ | ||
this.testHostManagerFactory = testHostManagerFactory; | ||
this.discoveryManager = this.testHostManagerFactory.GetDiscoveryManager(); | ||
} | ||
|
||
/// <summary> | ||
|
@@ -41,11 +43,9 @@ public void Initialize() | |
{ | ||
if(!this.IsInitialized) | ||
{ | ||
var discoveryManager = this.testHostManagerFactory.GetDiscoveryManager(); | ||
|
||
// 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>()); | ||
this.discoveryManager.Initialize(Enumerable.Empty<string>()); | ||
this.IsInitialized = true; | ||
} | ||
} | ||
|
@@ -57,25 +57,20 @@ public void Initialize() | |
/// <param name="eventHandler">EventHandler for handling discovery events from Engine</param> | ||
public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEventsHandler eventHandler) | ||
{ | ||
var discoveryManager = this.testHostManagerFactory.GetDiscoveryManager(); | ||
|
||
Task.Run(() => | ||
{ | ||
try | ||
{ | ||
// Initialize extension before discovery if it’s not initialized | ||
if (!this.IsInitialized) | ||
{ | ||
discoveryManager.Initialize(Enumerable.Empty<string>()); | ||
} | ||
discoveryManager.DiscoverTests(discoveryCriteria, eventHandler); | ||
this.Initialize(); | ||
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.Message); | ||
eventHandler.HandleLogMessage(TestMessageLevel.Error, exception.ToString()); | ||
eventHandler.HandleDiscoveryComplete(-1, new List<TestCase>(), true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,9 +14,10 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client | |
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.TesthostProtocol; | ||
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging; | ||
|
||
class InProcessProxyExecutionManager : IProxyExecutionManager | ||
internal class InProcessProxyExecutionManager : IProxyExecutionManager | ||
{ | ||
private ITestHostManagerFactory testHostManagerFactory; | ||
IExecutionManager executionManager; | ||
public bool IsInitialized { get; private set; } = false; | ||
|
||
/// <summary> | ||
|
@@ -35,32 +36,30 @@ public InProcessProxyExecutionManager() : this(new TestHostManagerFactory()) | |
internal InProcessProxyExecutionManager(ITestHostManagerFactory testHostManagerFactory) | ||
{ | ||
this.testHostManagerFactory = testHostManagerFactory; | ||
this.executionManager = this.testHostManagerFactory.GetExecutionManager(); | ||
} | ||
|
||
/// <summary> | ||
/// Initialize adapters. | ||
/// </summary> | ||
public void Initialize() | ||
{ | ||
if (!this.IsInitialized) | ||
{ | ||
var executionManager = this.testHostManagerFactory.GetExecutionManager(); | ||
|
||
// 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>()); | ||
this.IsInitialized = true; | ||
} | ||
} | ||
|
||
/// <inheritdoc/> | ||
public int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEventsHandler eventHandler) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: doc. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. fixed |
||
{ | ||
try | ||
{ | ||
var executionManager = this.testHostManagerFactory.GetExecutionManager(); | ||
|
||
// Initialize extension before execution if not already initialized | ||
if (!this.IsInitialized) | ||
{ | ||
executionManager.Initialize(Enumerable.Empty<string>()); | ||
} | ||
this.Initialize(); | ||
|
||
var executionContext = new TestExecutionContext( | ||
testRunCriteria.FrequencyOfRunStatsChangeEvent, | ||
|
@@ -89,8 +88,8 @@ public int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEventsHandler e | |
{ | ||
EqtTrace.Error("InProcessProxyexecutionManager.StartTestRun: Failed to start test run: {0}", exception); | ||
|
||
// Send a discovery complete to caller. | ||
eventHandler.HandleLogMessage(TestMessageLevel.Error, exception.Message); | ||
// 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); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -60,7 +60,7 @@ public void Initialize(IEnumerable<string> pathToAdditionalExtensions) | |
{ | ||
this.testPlatformEventSource.AdapterSearchStart(); | ||
|
||
if (pathToAdditionalExtensions != null && pathToAdditionalExtensions.Count() > 0) | ||
if (pathToAdditionalExtensions != null && pathToAdditionalExtensions.Any()) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we use pathToAdditionalExtensions.Any() instead of pathToAdditionalExtensions.Count() > 0? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes we can use |
||
// Start using these additional extensions | ||
TestPluginCache.Instance.DefaultExtensionPaths = pathToAdditionalExtensions; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,17 +31,19 @@ public class TestEngine : ITestEngine | |
private readonly TestRuntimeProviderManager testHostProviderManager; | ||
private ITestExtensionManager testExtensionManager; | ||
private IProcessHelper processHelper; | ||
private bool isInIsolation = false; | ||
|
||
#endregion | ||
|
||
public TestEngine() : this(TestRuntimeProviderManager.Instance, new ProcessHelper()) | ||
public TestEngine(bool isInIsolation = false) : this(TestRuntimeProviderManager.Instance, new ProcessHelper(), isInIsolation) | ||
{ | ||
} | ||
|
||
protected TestEngine(TestRuntimeProviderManager testHostProviderManager, IProcessHelper processHelper) | ||
protected TestEngine(TestRuntimeProviderManager testHostProviderManager, IProcessHelper processHelper, bool isInIsolation) | ||
{ | ||
this.testHostProviderManager = testHostProviderManager; | ||
this.processHelper = processHelper; | ||
this.isInIsolation = isInIsolation; | ||
} | ||
|
||
#region ITestEngine implementation | ||
|
@@ -63,7 +65,7 @@ public IProxyDiscoveryManager GetDiscoveryManager(ITestRuntimeProvider testHostM | |
{ | ||
var parallelLevel = this.VerifyParallelSettingAndCalculateParallelLevel(discoveryCriteria.Sources.Count(), discoveryCriteria.RunSettings); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this can be moved below There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in next commit. |
||
|
||
if (this.ShouldRunInNoIsolation(discoveryCriteria.RunSettings)) | ||
if (this.ShouldRunInNoIsolation(discoveryCriteria.RunSettings, parallelLevel > 1, false)) | ||
{ | ||
return new InProcessProxyDiscoveryManager(); | ||
} | ||
|
@@ -95,7 +97,7 @@ public IProxyExecutionManager GetExecutionManager(ITestRuntimeProvider testHostM | |
|
||
var isDataCollectorEnabled = XmlRunSettingsUtilities.IsDataCollectionEnabled(testRunCriteria.TestRunSettings); | ||
|
||
if (parallelLevel <= 1 && !isDataCollectorEnabled && this.ShouldRunInNoIsolation(testRunCriteria.TestRunSettings)) | ||
if (this.ShouldRunInNoIsolation(testRunCriteria.TestRunSettings, parallelLevel > 1, isDataCollectorEnabled)) | ||
{ | ||
return new InProcessProxyExecutionManager(); | ||
} | ||
|
@@ -208,11 +210,20 @@ private int VerifyParallelSettingAndCalculateParallelLevel(int sourceCount, stri | |
return parallelLevelToUse; | ||
} | ||
|
||
private bool ShouldRunInNoIsolation(string runsettings) | ||
private bool ShouldRunInNoIsolation(string runsettings, bool isParallelEnabled, bool isDataCollectorEnabled) | ||
{ | ||
if(this.isInIsolation == true) | ||
{ | ||
if (EqtTrace.IsInfoEnabled) | ||
{ | ||
EqtTrace.Info("TestEngine.ShouldRunInNoIsolation: running test in isolation"); | ||
} | ||
return false; | ||
} | ||
|
||
var currentProcessPath = this.processHelper.GetCurrentProcessFileName(); | ||
|
||
// If running with the dotnet executable, then dont run in NoIsolation | ||
// If running with the dotnet executable, then dont run in InProcess | ||
if (currentProcessPath.EndsWith("dotnet", StringComparison.OrdinalIgnoreCase) | ||
|| currentProcessPath.EndsWith("dotnet.exe", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
|
@@ -221,12 +232,24 @@ private bool ShouldRunInNoIsolation(string runsettings) | |
|
||
var runConfiguration = XmlRunSettingsUtilities.GetRunConfigurationNode(runsettings); | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add a comment specifying when will we enable InProc run There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed |
||
if (runConfiguration.InProcess && | ||
// Return true if | ||
// 1) Not running in parallel | ||
// 2) Data collector is not enabled | ||
// 3) Target framework is x86 or anyCpu | ||
// 4) DisableAppDomain is false | ||
// 5) Not running in design mode | ||
// 6) target framework is NETFramework (Desktop test) | ||
if (!isParallelEnabled && | ||
!isDataCollectorEnabled && | ||
(runConfiguration.TargetPlatform == Architecture.X86 || runConfiguration.TargetPlatform == Architecture.AnyCPU) && | ||
!runConfiguration.DisableAppDomain && | ||
!runConfiguration.DesignMode && | ||
!(runConfiguration.TargetFrameworkVersion.Name.IndexOf("netstandard", StringComparison.OrdinalIgnoreCase) >= 0 | ||
|| runConfiguration.TargetFrameworkVersion.Name.IndexOf("netcoreapp", StringComparison.OrdinalIgnoreCase) >= 0)) | ||
runConfiguration.TargetFrameworkVersion.Name.IndexOf("netframework", StringComparison.OrdinalIgnoreCase) >= 0) | ||
{ | ||
if(EqtTrace.IsInfoEnabled) | ||
{ | ||
EqtTrace.Info("TestEngine.ShouldRunInNoIsolation: running test in process(inside vstest.console.exe process)"); | ||
} | ||
return true ; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Log eqttrace message on successful/unsuccessful using of inproc. Give warning on using inproc option for not supported target frameworks. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed! |
||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Explicit annotation for types.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in next commit.