Skip to content
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

Refined runsettings matching criteria for test sessions #3610

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;

using Microsoft.VisualStudio.TestPlatform.Common.Telemetry;
using Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Client;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Engine;
using Microsoft.VisualStudio.TestPlatform.ObjectModel.Utilities;
using Microsoft.VisualStudio.TestPlatform.Utilities;

using CrossPlatResources = Microsoft.VisualStudio.TestPlatform.CrossPlatEngine.Resources.Resources;

Expand Down Expand Up @@ -42,6 +45,7 @@ private enum TestSessionState
private readonly IList<ProxyOperationManagerContainer> _proxyContainerList;
private readonly IDictionary<string, int> _proxyMap;
private readonly Stopwatch _testSessionStopwatch;
private IDictionary<string, string> _runSettingsEnvironmentVariables;

/// <summary>
/// Initializes a new instance of the <see cref="ProxyTestSessionManager"/> class.
Expand All @@ -61,6 +65,7 @@ public ProxyTestSessionManager(

_proxyContainerList = new List<ProxyOperationManagerContainer>();
_proxyMap = new Dictionary<string, int>();
_runSettingsEnvironmentVariables = new Dictionary<string, string>();
_testSessionStopwatch = new Stopwatch();
}

Expand Down Expand Up @@ -227,10 +232,7 @@ public virtual ProxyOperationManager DequeueProxy(string source, string runSetti
// We must ensure the current run settings match the run settings from when the
// testhost was started. If not, throw an exception to force the caller to create
// its own proxy instead.
//
// TODO (copoiena): This run settings match is rudimentary. We should refine the
// match criteria in the future.
if (!_testSessionCriteria.RunSettings.Equals(runSettings))
if (!CheckRunSettingsAreCompatible(runSettings))
{
throw new InvalidOperationException(
string.Format(
Expand Down Expand Up @@ -382,6 +384,35 @@ private void DisposeProxies()
_proxyMap.Clear();
}
}

private bool CheckRunSettingsAreCompatible(string requestRunSettings)
cvpoienaru marked this conversation as resolved.
Show resolved Hide resolved
{
if (_runSettingsEnvironmentVariables.Count == 0)
{
_runSettingsEnvironmentVariables = InferRunSettingsHelper.GetEnvironmentVariables(
cvpoienaru marked this conversation as resolved.
Show resolved Hide resolved
_testSessionCriteria.RunSettings)
?? _runSettingsEnvironmentVariables;
}

// Environment variable sets should be identical, otherwise it's not safe to reuse the
// already running testhosts.
var requestEnvironmentVariables = InferRunSettingsHelper.GetEnvironmentVariables(requestRunSettings);
if (requestEnvironmentVariables != null
&& _runSettingsEnvironmentVariables != null
&& (requestEnvironmentVariables.Count != _runSettingsEnvironmentVariables.Count
|| requestEnvironmentVariables.Except(_runSettingsEnvironmentVariables).Any()))
{
return false;
}

// Data collection is not supported for test sessions yet.
if (XmlRunSettingsUtilities.IsDataCollectionEnabled(requestRunSettings))
cvpoienaru marked this conversation as resolved.
Show resolved Hide resolved
{
return false;
}

return true;
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,42 @@ public class ProxyTestSessionManagerTests
@"C:\temp\FakeTestAsset7.dll",
@"C:\temp\FakeTestAsset8.dll",
};
private readonly string _runSettingsNoEnvVars = @"<?xml version=""1.0"" encoding=""utf-8""?>
<RunSettings>
<RunConfiguration>
</RunConfiguration>
</RunSettings>";
private readonly string _runSettingsOneEnvVar = @"<?xml version=""1.0"" encoding=""utf-8""?>
<RunSettings>
<RunConfiguration>
<EnvironmentVariables>
<AAA>Test1</AAA>
</EnvironmentVariables>
</RunConfiguration>
</RunSettings>";
private readonly string _runSettingsTwoEnvVars = @"<?xml version=""1.0"" encoding=""utf-8""?>
<RunSettings>
<RunConfiguration>
<EnvironmentVariables>
<AAA>Test1</AAA>
<BBB>Test2</BBB>
</EnvironmentVariables>
</RunConfiguration>
</RunSettings>";
private readonly string _runSettingsTwoEnvVarsAndDataCollectors = @"<?xml version=""1.0"" encoding=""utf-8""?>
<RunSettings>
<RunConfiguration>
<EnvironmentVariables>
<AAA>Test1</AAA>
<BBB>Test2</BBB>
</EnvironmentVariables>
</RunConfiguration>
<DataCollectionRunSettings>
<DataCollectors>
<DataCollector friendlyName=""blame"" enabled=""True""></DataCollector>
</DataCollectors>
</DataCollectionRunSettings>
</RunSettings>";
private readonly string _fakeRunSettings = "FakeRunSettings";
private readonly ProtocolConfig _protocolConfig = new() { Version = 1 };
private Mock<ITestSessionEventsHandler> _mockEventsHandler;
Expand Down Expand Up @@ -281,7 +317,7 @@ public void DequeueProxyShouldSucceedIfIdentificationCriteriaAreMet()
mockProxyOperationManager.Setup(pom => pom.SetupChannel(It.IsAny<IEnumerable<string>>(), It.IsAny<string>()))
.Returns(true);

var testSessionCriteria = CreateTestSession(_fakeTestSources, _fakeRunSettings);
var testSessionCriteria = CreateTestSession(_fakeTestSources, _runSettingsNoEnvVars);
var proxyManager = CreateProxy(testSessionCriteria, mockProxyOperationManager.Object);

// StartSession should succeed.
Expand All @@ -302,7 +338,7 @@ public void DequeueProxyShouldSucceedIfIdentificationCriteriaAreMet()
// Second call to DequeueProxy fails because of runsettings mismatch.
Assert.ThrowsException<InvalidOperationException>(() => proxyManager.DequeueProxy(
testSessionCriteria.Sources[0],
"DummyRunSettings"));
_runSettingsOneEnvVar));

// Third call to DequeueProxy succeeds.
Assert.AreEqual(proxyManager.DequeueProxy(
Expand All @@ -316,14 +352,92 @@ public void DequeueProxyShouldSucceedIfIdentificationCriteriaAreMet()
testSessionCriteria.RunSettings));
}

[TestMethod]
public void DequeueProxyShouldFailIfRunSettingsMatchingFails()
{
var mockProxyOperationManager = new Mock<ProxyOperationManager>(null, null, null);
mockProxyOperationManager.Setup(pom => pom.SetupChannel(It.IsAny<IEnumerable<string>>(), It.IsAny<string>()))
.Returns(true);

var testSessionCriteria = CreateTestSession(_fakeTestSources, _runSettingsOneEnvVar);
var proxyManager = CreateProxy(testSessionCriteria, mockProxyOperationManager.Object);

// StartSession should succeed.
Assert.IsTrue(proxyManager.StartSession(_mockEventsHandler.Object, _mockRequestData.Object));
mockProxyOperationManager.Verify(pom => pom.SetupChannel(
It.IsAny<IEnumerable<string>>(),
testSessionCriteria.RunSettings),
Times.Exactly(testSessionCriteria.Sources.Count));
_mockEventsHandler.Verify(eh => eh.HandleStartTestSessionComplete(
It.IsAny<StartTestSessionCompleteEventArgs>()),
Times.Once);

// This call to DequeueProxy fails because of runsettings mismatch.
Assert.ThrowsException<InvalidOperationException>(() => proxyManager.DequeueProxy(
testSessionCriteria.Sources[0],
_runSettingsTwoEnvVars));
}

[TestMethod]
public void DequeueProxyShouldFailIfRunSettingsMatchingFailsFor2EnvVariables()
{
var mockProxyOperationManager = new Mock<ProxyOperationManager>(null, null, null);
mockProxyOperationManager.Setup(pom => pom.SetupChannel(It.IsAny<IEnumerable<string>>(), It.IsAny<string>()))
.Returns(true);

var testSessionCriteria = CreateTestSession(_fakeTestSources, _runSettingsTwoEnvVars);
var proxyManager = CreateProxy(testSessionCriteria, mockProxyOperationManager.Object);

// StartSession should succeed.
Assert.IsTrue(proxyManager.StartSession(_mockEventsHandler.Object, _mockRequestData.Object));
mockProxyOperationManager.Verify(pom => pom.SetupChannel(
It.IsAny<IEnumerable<string>>(),
testSessionCriteria.RunSettings),
Times.Exactly(testSessionCriteria.Sources.Count));
_mockEventsHandler.Verify(eh => eh.HandleStartTestSessionComplete(
It.IsAny<StartTestSessionCompleteEventArgs>()),
Times.Once);

// This call to DequeueProxy fails because of runsettings mismatch.
Assert.ThrowsException<InvalidOperationException>(() => proxyManager.DequeueProxy(
testSessionCriteria.Sources[0],
_runSettingsOneEnvVar));
}

[TestMethod]
public void DequeueProxyShouldFailIfRunSettingsMatchingFailsForDataCollectors()
{
var mockProxyOperationManager = new Mock<ProxyOperationManager>(null, null, null);
mockProxyOperationManager.Setup(pom => pom.SetupChannel(It.IsAny<IEnumerable<string>>(), It.IsAny<string>()))
.Returns(true);

var testSessionCriteria = CreateTestSession(_fakeTestSources, _runSettingsTwoEnvVars);
var proxyManager = CreateProxy(testSessionCriteria, mockProxyOperationManager.Object);

// StartSession should succeed.
Assert.IsTrue(proxyManager.StartSession(_mockEventsHandler.Object, _mockRequestData.Object));
mockProxyOperationManager.Verify(pom => pom.SetupChannel(
It.IsAny<IEnumerable<string>>(),
testSessionCriteria.RunSettings),
Times.Exactly(testSessionCriteria.Sources.Count));
_mockEventsHandler.Verify(eh => eh.HandleStartTestSessionComplete(
It.IsAny<StartTestSessionCompleteEventArgs>()),
Times.Once);

// This call to DequeueProxy fails because of runsettings mismatch.
Assert.ThrowsException<InvalidOperationException>(() => proxyManager.DequeueProxy(
testSessionCriteria.Sources[0],
_runSettingsTwoEnvVarsAndDataCollectors));
}

[TestMethod]
public void EnqueueProxyShouldSucceedIfIdentificationCriteriaAreMet()
{
var mockProxyOperationManager = new Mock<ProxyOperationManager>(null, null, null);
mockProxyOperationManager.Setup(pom => pom.SetupChannel(It.IsAny<IEnumerable<string>>(), It.IsAny<string>()))
.Returns(true);

var testSessionCriteria = CreateTestSession(_fakeTestSources, _fakeRunSettings);
var testSessionCriteria = CreateTestSession(_fakeTestSources, _runSettingsNoEnvVars);
var proxyManager = CreateProxy(testSessionCriteria, mockProxyOperationManager.Object);

// Validate sanity checks.
Expand Down