diff --git a/src/Microsoft.TestPlatform.Common/DataCollection/DataCollectionManager.cs b/src/Microsoft.TestPlatform.Common/DataCollection/DataCollectionManager.cs index dbebbe63f9..fe3d2aa44c 100644 --- a/src/Microsoft.TestPlatform.Common/DataCollection/DataCollectionManager.cs +++ b/src/Microsoft.TestPlatform.Common/DataCollection/DataCollectionManager.cs @@ -24,6 +24,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.DataCollector internal class DataCollectionManager : IDataCollectionManager { private static object syncObject = new object(); + private const string CodeCoverageFriendlyName = "Code Coverage"; /// /// Value indicating whether data collection is currently enabled. @@ -591,7 +592,11 @@ private Dictionary GetEnvironmentVari var failedCollectors = new List(); unloadedAnyCollector = false; var dataCollectorEnvironmentVariable = new Dictionary(StringComparer.OrdinalIgnoreCase); - foreach (var dataCollectorInfo in this.RunDataCollectors.Values) + + // Ordering here is temporary to enable Fakes + Code Coverage integration in scenarios when Fakes decides to instrument code using + // CLR Instrumentation Engine. This code will be cleaned when both Fakes and Code Coverage will fully switch to CLR Instrumentation Engine. + foreach (var dataCollectorInfo in this.RunDataCollectors.Values. + OrderBy(rdc => rdc.DataCollectorConfig.FriendlyName.Equals(CodeCoverageFriendlyName, StringComparison.OrdinalIgnoreCase) ? 1 : 0)) { try { @@ -649,16 +654,24 @@ private void AddCollectorEnvironmentVariables( else { // Data collector is overriding an already requested variable, possibly an error. - dataCollectionWrapper.Logger.LogError( - this.dataCollectionEnvironmentContext.SessionDataCollectionContext, - string.Format( + var message = string.Format( CultureInfo.CurrentUICulture, Resources.Resources.DataCollectorRequestedDuplicateEnvironmentVariable, collectorFriendlyName, namevaluepair.Key, namevaluepair.Value, alreadyRequestedVariable.FirstDataCollectorThatRequested, - alreadyRequestedVariable.Value)); + alreadyRequestedVariable.Value); + + if(collectorFriendlyName.Equals(CodeCoverageFriendlyName, StringComparison.OrdinalIgnoreCase)) + { + // Do not treat this as error for Code Coverage Data Collector. This is expected in some Fakes integration scenarios + EqtTrace.Info(message); + } + else + { + dataCollectionWrapper.Logger.LogError(this.dataCollectionEnvironmentContext.SessionDataCollectionContext, message); + } } } else diff --git a/test/datacollector.UnitTests/DataCollectionManagerTests.cs b/test/datacollector.UnitTests/DataCollectionManagerTests.cs index 41e6486a8b..81e98d6b95 100644 --- a/test/datacollector.UnitTests/DataCollectionManagerTests.cs +++ b/test/datacollector.UnitTests/DataCollectionManagerTests.cs @@ -5,6 +5,7 @@ namespace Microsoft.VisualStudio.TestPlatform.Common.DataCollector.UnitTests { using System; using System.Collections.Generic; + using System.Linq; using System.Reflection; using System.Xml; @@ -27,7 +28,9 @@ public class DataCollectionManagerTests private string uri; private Mock mockMessageSink; private Mock mockDataCollector; + private Mock mockCodeCoverageDataCollector; private List> envVarList; + private List> codeCoverageEnvVarList; private Mock mockDataCollectionAttachmentManager; public DataCollectionManagerTests() @@ -35,14 +38,17 @@ public DataCollectionManagerTests() this.friendlyName = "CustomDataCollector"; this.uri = "my://custom/datacollector"; this.envVarList = new List>(); + this.codeCoverageEnvVarList = new List>(); this.mockDataCollector = new Mock(); this.mockDataCollector.As().Setup(x => x.GetTestExecutionEnvironmentVariables()).Returns(this.envVarList); + this.mockCodeCoverageDataCollector = new Mock(); + this.mockCodeCoverageDataCollector.As().Setup(x => x.GetTestExecutionEnvironmentVariables()).Returns(this.codeCoverageEnvVarList); this.dataCollectorSettings = string.Format(this.defaultRunSettings, string.Format(this.defaultDataCollectionSettings, this.friendlyName, this.uri, this.mockDataCollector.Object.GetType().AssemblyQualifiedName, typeof(DataCollectionManagerTests).GetTypeInfo().Assembly.Location, string.Empty)); this.mockMessageSink = new Mock(); this.mockDataCollectionAttachmentManager = new Mock(); this.mockDataCollectionAttachmentManager.SetReturnsDefault>(new List()); - this.dataCollectionManager = new TestableDataCollectionManager(this.mockDataCollectionAttachmentManager.Object, this.mockMessageSink.Object, this.mockDataCollector.Object); + this.dataCollectionManager = new TestableDataCollectionManager(this.mockDataCollectionAttachmentManager.Object, this.mockMessageSink.Object, this.mockDataCollector.Object, this.mockCodeCoverageDataCollector.Object); } [TestMethod] @@ -219,6 +225,24 @@ public void InitializeDataCollectorsShouldReturnFirstEnvironmentVariableIfMoreTh Assert.AreEqual("value", result["key"]); } + [TestMethod] + public void InitializeDataCollectorsShouldReturnOtherThanCodeCoverageEnvironmentVariableIfMoreThanOneVariablesWithSameKeyIsSpecified() + { + this.envVarList.Add(new KeyValuePair("cor_profiler", "clrie")); + this.codeCoverageEnvVarList.Add(new KeyValuePair("cor_profiler", "direct")); + this.codeCoverageEnvVarList.Add(new KeyValuePair("clrie_profiler_vanguard", "path")); + + this.dataCollectorSettings = string.Format(this.defaultRunSettings, + string.Format(this.defaultDataCollectionSettings, "Code Coverage", "my://custom/ccdatacollector", this.mockDataCollector.Object.GetType().AssemblyQualifiedName, typeof(DataCollectionManagerTests).GetTypeInfo().Assembly.Location, string.Empty) + + string.Format(this.defaultDataCollectionSettings, this.friendlyName, this.uri, this.mockDataCollector.Object.GetType().AssemblyQualifiedName, typeof(DataCollectionManagerTests).GetTypeInfo().Assembly.Location, string.Empty)); + + var result = this.dataCollectionManager.InitializeDataCollectors(this.dataCollectorSettings); + + Assert.AreEqual(2, result.Count); + Assert.AreEqual("clrie", result["cor_profiler"]); + Assert.AreEqual("path", result["clrie_profiler_vanguard"]); + } + [TestMethod] public void SessionStartedShouldReturnFalseIfDataCollectionIsNotConfiguredInRunSettings() { @@ -457,10 +481,12 @@ private void SetupMockDataCollector(Action