Skip to content

Commit

Permalink
Specifying environment variables in RunSettings file (#2128)
Browse files Browse the repository at this point in the history
* Specifying environment variables in RunSettings file
  • Loading branch information
vagisha-nidhi authored Aug 20, 2019
1 parent 9238308 commit 485de78
Show file tree
Hide file tree
Showing 13 changed files with 331 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public void DiscoverTests(DiscoveryCriteria discoveryCriteria, ITestDiscoveryEve
this.baseTestDiscoveryEventsHandler = eventHandler;
try
{
this.isCommunicationEstablished = this.SetupChannel(discoveryCriteria.Sources);
this.isCommunicationEstablished = this.SetupChannel(discoveryCriteria.Sources, discoveryCriteria.RunSettings);

if (this.isCommunicationEstablished)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine.ClientProtocol;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Host;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Logging;
using Microsoft.VisualStudio.TestPlatform.Utilities;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers;
using Microsoft.VisualStudio.TestPlatform.Utilities.Helpers.Interfaces;

Expand Down Expand Up @@ -101,17 +102,18 @@ public virtual int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEventsH
{
EqtTrace.Verbose("ProxyExecutionManager: Test host is always Lazy initialize.");
}
var testPackages = new List<string>(testRunCriteria.HasSpecificSources ? testRunCriteria.Sources :

var testSources = new List<string>(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.isCommunicationEstablished = this.SetupChannel(testSources, testRunCriteria.TestRunSettings);

if (this.isCommunicationEstablished)
{
this.CancellationTokenSource.Token.ThrowTestPlatformExceptionIfCancellationRequested();

this.InitializeExtensions(testPackages);
this.InitializeExtensions(testSources);

// This code should be in sync with InProcessProxyExecutionManager.StartTestRun executionContext
var executionContext = new TestExecutionContext(
Expand All @@ -131,12 +133,12 @@ public virtual int StartTestRun(TestRunCriteria testRunCriteria, ITestRunEventsH

if (testRunCriteria.HasSpecificSources)
{
var runRequest = testRunCriteria.CreateTestRunCriteriaForSources(testHostManager, runsettings, executionContext, testPackages);
var runRequest = testRunCriteria.CreateTestRunCriteriaForSources(testHostManager, runsettings, executionContext, testSources);
this.RequestSender.StartTestRun(runRequest, this);
}
else
{
var runRequest = testRunCriteria.CreateTestRunCriteriaForTests(testHostManager, runsettings, executionContext, testPackages);
var runRequest = testRunCriteria.CreateTestRunCriteriaForTests(testHostManager, runsettings, executionContext, testSources);
this.RequestSender.StartTestRun(runRequest, this);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client
using CrossPlatEngineResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources;
using CommunicationUtilitiesResources = Microsoft.VisualStudio.TestPlatform.CommunicationUtilities.Resources.Resources;
using CoreUtilitiesConstants = Microsoft.VisualStudio.TestPlatform.CoreUtilities.Constants;

/// <summary>
/// Base class for any operations that the client needs to drive through the engine.
/// </summary>
Expand Down Expand Up @@ -96,7 +96,7 @@ protected ProxyOperationManager(IRequestData requestData, ITestRequestSender req
/// <returns>
/// Returns true if Communation is established b/w runner and host
/// </returns>
public virtual bool SetupChannel(IEnumerable<string> sources)
public virtual bool SetupChannel(IEnumerable<string> sources, string runSettings)
{
this.CancellationTokenSource.Token.ThrowTestPlatformExceptionIfCancellationRequested();
var connTimeout = EnvironmentHelper.GetConnectionTimeout();
Expand All @@ -120,8 +120,11 @@ public virtual bool SetupChannel(IEnumerable<string> sources)
this.testHostManager.HostLaunched += this.TestHostManagerHostLaunched;
this.testHostManager.HostExited += this.TestHostManagerHostExited;

// Get envVars from run settings
var envVars = InferRunSettingsHelper.GetEnvironmentVariables(runSettings);

// Get the test process start info
var testHostStartInfo = this.UpdateTestProcessStartInfo(this.testHostManager.GetTestHostProcessStartInfo(sources, null, connectionInfo));
var testHostStartInfo = this.UpdateTestProcessStartInfo(this.testHostManager.GetTestHostProcessStartInfo(sources, envVars, connectionInfo));
try
{
// Launch the test host.
Expand Down
46 changes: 46 additions & 0 deletions src/Microsoft.TestPlatform.Utilities/InferRunSettingsHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Utilities
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;
using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Globalization;
using System.IO;
using System.Text;
Expand Down Expand Up @@ -36,6 +37,7 @@ public class InferRunSettingsHelper
private const string TargetFrameworkNodePath = @"/RunSettings/RunConfiguration/TargetFrameworkVersion";
private const string ResultsDirectoryNodePath = @"/RunSettings/RunConfiguration/ResultsDirectory";
private const string TargetDeviceNodePath = @"/RunSettings/RunConfiguration/TargetDevice";
private const string EnvironmentVariablesNodePath = @"/RunSettings/RunConfiguration/EnvironmentVariables";
private const string multiTargettingForwardLink = @"http://go.microsoft.com/fwlink/?LinkID=236877&clcid=0x409";

// To make things compatible for older runsettings
Expand Down Expand Up @@ -377,6 +379,50 @@ private static List<string> GetNodeAttributes(XPathNavigator node)
return null;
}

/// <summary>
/// Returns a dictionary of environment variables given in run settings
/// </summary>
/// <param name="runsettingsXml">The run settings xml string</param>
/// <returns>Environment Variables Dictionary</returns>
public static Dictionary<string, string> GetEnvironmentVariables(string runSettings)
{
Dictionary<string, string> environmentVariables = null;
try
{
using (var stream = new StringReader(runSettings))
using (var reader = XmlReader.Create(stream, XmlRunSettingsUtilities.ReaderSettings))
{
var document = new XmlDocument();
document.Load(reader);
var runSettingsNavigator = document.CreateNavigator();

var node = runSettingsNavigator.SelectSingleNode(EnvironmentVariablesNodePath);
if (node == null)
{
return null;
}

environmentVariables = new Dictionary<string, string>();
var childNodes = node.SelectChildren(XPathNodeType.Element);

while (childNodes.MoveNext())
{
if (!environmentVariables.ContainsKey(childNodes.Current.Name))
{
environmentVariables.Add(childNodes.Current.Name, childNodes.Current?.Value);
}
}
}
}
catch (Exception ex)
{
EqtTrace.Error("Error while trying to read environment variables settings. Message: {0}", ex.ToString());
return null;
}

return environmentVariables;
}

/// <summary>
/// Updates the <c>RunConfiguration.TargetPlatform</c> value for a run settings. if the value is already set, behavior depends on overwrite.
/// </summary>
Expand Down
7 changes: 7 additions & 0 deletions src/vstest.console/Processors/RunSettingsArgumentProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Processors
{
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.Contracts;
using System.Globalization;
Expand Down Expand Up @@ -137,6 +138,12 @@ public void Initialize(string argument)
this.runSettingsManager.AddDefaultRunSettings();

this.commandLineOptions.SettingsFile = argument;

if (this.runSettingsManager.QueryRunSettingsNode("RunConfiguration.EnvironmentVariables") != null)
{
this.commandLineOptions.InIsolation = true;
this.runSettingsManager.UpdateRunSettingsNode(InIsolationArgumentExecutor.RunSettingsPath, "true");
}
}
catch (XmlException exception)
{
Expand Down
31 changes: 31 additions & 0 deletions test/Microsoft.TestPlatform.AcceptanceTests/RunsettingsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,37 @@ public void LegacySettingsAssemblyResolution(RunnerInfo runnerInfo)

#endregion

#region RunSettings With EnvironmentVariables Settings Tests

[TestMethod]
[NetFullTargetFrameworkDataSource]
[NetCoreTargetFrameworkDataSource]
public void EnvironmentVariablesSettingsShouldSetEnvironmentVariables(RunnerInfo runnerInfo)
{
AcceptanceTestBase.SetTestEnvironment(this.testEnvironment, runnerInfo);

var testAssemblyPath = this.GetAssetFullPath("EnvironmentVariablesTestProject.dll");

var runsettingsXml = @"<RunSettings>
<RunConfiguration>
<EnvironmentVariables>
<RANDOM_PATH>C:\temp</RANDOM_PATH>
</EnvironmentVariables>
</RunConfiguration>
</RunSettings>";

File.WriteAllText(this.runsettingsPath, runsettingsXml);

var arguments = PrepareArguments(
testAssemblyPath,
string.Empty,
this.runsettingsPath, this.FrameworkArgValue, runnerInfo.InIsolationValue);
this.InvokeVsTest(arguments);
this.ValidateSummaryStatus(1, 0, 0);
}

#endregion

private string GetRunsettingsFilePath(Dictionary<string, string> runConfigurationDictionary)
{
var runsettingsPath = Path.Combine(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -334,19 +334,23 @@ public void StartTestRunShouldInitializeExtensionsWithExistingDataCOllectorExten
[TestMethod]
public void SetupChannelShouldThrowExceptionIfClientConnectionTimeout()
{
string runsettings = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<RunSettings>\r\n <DataCollectionRunSettings>\r\n <DataCollectors >{0}</DataCollectors>\r\n </DataCollectionRunSettings>\r\n</RunSettings>";

this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny<int>(), It.IsAny<CancellationToken>())).Returns(false);
this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny<TestProcessStartInfo>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(false));

Assert.ThrowsException<TestPlatformException>(() => this.testExecutionManager.SetupChannel(new List<string> { "source.dll" }));
Assert.ThrowsException<TestPlatformException>(() => this.testExecutionManager.SetupChannel(new List<string> { "source.dll" }, runsettings));
}

[TestMethod]
public void SetupChannelShouldThrowExceptionIfTestHostExitedBeforeConnectionIsEstablished()
{
string runsettings = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<RunSettings>\r\n <DataCollectionRunSettings>\r\n <DataCollectors >{0}</DataCollectors>\r\n </DataCollectionRunSettings>\r\n</RunSettings>";

this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny<int>(), It.IsAny<CancellationToken>())).Returns(false);
this.mockTestHostManager.Setup(tmh => tmh.LaunchTestHostAsync(It.IsAny<TestProcessStartInfo>(), It.IsAny<CancellationToken>())).Returns(Task.FromResult(true)).Callback(() => { this.mockTestHostManager.Raise(t => t.HostExited += null, new HostProviderEventArgs("I crashed!")); });

Assert.AreEqual(string.Format(CrossPlatEngineResources.Resources.TestHostExitedWithError, "I crashed!"), Assert.ThrowsException<TestPlatformException>(() => this.testExecutionManager.SetupChannel(new List<string> { "source.dll" })).Message);
Assert.AreEqual(string.Format(CrossPlatEngineResources.Resources.TestHostExitedWithError, "I crashed!"), Assert.ThrowsException<TestPlatformException>(() => this.testExecutionManager.SetupChannel(new List<string> { "source.dll" }, runsettings)).Message);
}

[TestMethod]
Expand Down Expand Up @@ -522,9 +526,11 @@ public void StartTestRunShouldInitiateTestRunForTestsThroughTheServer()
[TestMethod]
public void CloseShouldSignalToServerSessionEndIfTestHostWasLaunched()
{
string runsettings = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<RunSettings>\r\n <DataCollectionRunSettings>\r\n <DataCollectors >{0}</DataCollectors>\r\n </DataCollectionRunSettings>\r\n</RunSettings>";

this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny<int>(), It.IsAny<CancellationToken>())).Returns(true);

this.testExecutionManager.SetupChannel(new List<string> { "source.dll" });
this.testExecutionManager.SetupChannel(new List<string> { "source.dll" }, runsettings);

this.testExecutionManager.Close();

Expand All @@ -542,9 +548,11 @@ public void CloseShouldNotSendSignalToServerSessionEndIfTestHostWasNotLaunched()
[TestMethod]
public void CloseShouldSignalServerSessionEndEachTime()
{
string runsettings = "<?xml version=\"1.0\" encoding=\"utf-16\"?>\r\n<RunSettings>\r\n <DataCollectionRunSettings>\r\n <DataCollectors >{0}</DataCollectors>\r\n </DataCollectionRunSettings>\r\n</RunSettings>";

this.mockRequestSender.Setup(s => s.WaitForRequestHandlerConnection(It.IsAny<int>(), It.IsAny<CancellationToken>())).Returns(true);

this.testExecutionManager.SetupChannel(new List<string> { "source.dll" });
this.testExecutionManager.SetupChannel(new List<string> { "source.dll" }, runsettings);

this.testExecutionManager.Close();
this.testExecutionManager.Close();
Expand Down
Loading

0 comments on commit 485de78

Please sign in to comment.