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

Temporary code to enable correct Fakes and Code Coverage integration #2604

Merged
merged 2 commits into from
Oct 23, 2020
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -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";

/// <summary>
/// Value indicating whether data collection is currently enabled.
Expand Down Expand Up @@ -591,7 +592,11 @@ private Dictionary<string, DataCollectionEnvironmentVariable> GetEnvironmentVari
var failedCollectors = new List<DataCollectorInformation>();
unloadedAnyCollector = false;
var dataCollectorEnvironmentVariable = new Dictionary<string, DataCollectionEnvironmentVariable>(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
{
Expand Down Expand Up @@ -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
Expand Down
49 changes: 46 additions & 3 deletions test/datacollector.UnitTests/DataCollectionManagerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -27,22 +28,27 @@ public class DataCollectionManagerTests
private string uri;
private Mock<IMessageSink> mockMessageSink;
private Mock<DataCollector2> mockDataCollector;
private Mock<CodeCoverageDataCollector> mockCodeCoverageDataCollector;
private List<KeyValuePair<string, string>> envVarList;
private List<KeyValuePair<string, string>> codeCoverageEnvVarList;
private Mock<IDataCollectionAttachmentManager> mockDataCollectionAttachmentManager;

public DataCollectionManagerTests()
{
this.friendlyName = "CustomDataCollector";
this.uri = "my://custom/datacollector";
this.envVarList = new List<KeyValuePair<string, string>>();
this.codeCoverageEnvVarList = new List<KeyValuePair<string, string>>();
this.mockDataCollector = new Mock<DataCollector2>();
this.mockDataCollector.As<ITestExecutionEnvironmentSpecifier>().Setup(x => x.GetTestExecutionEnvironmentVariables()).Returns(this.envVarList);
this.mockCodeCoverageDataCollector = new Mock<CodeCoverageDataCollector>();
this.mockCodeCoverageDataCollector.As<ITestExecutionEnvironmentSpecifier>().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<IMessageSink>();
this.mockDataCollectionAttachmentManager = new Mock<IDataCollectionAttachmentManager>();
this.mockDataCollectionAttachmentManager.SetReturnsDefault<List<AttachmentSet>>(new List<AttachmentSet>());

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]
Expand Down Expand Up @@ -219,6 +225,24 @@ public void InitializeDataCollectorsShouldReturnFirstEnvironmentVariableIfMoreTh
Assert.AreEqual("value", result["key"]);
}

[TestMethod]
public void InitializeDataCollectorsShouldReturnOtherThanCodeCoverageEnvironmentVariableIfMoreThanOneVariablesWithSameKeyIsSpecified()
{
this.envVarList.Add(new KeyValuePair<string, string>("cor_profiler", "clrie"));
this.codeCoverageEnvVarList.Add(new KeyValuePair<string, string>("cor_profiler", "direct"));
this.codeCoverageEnvVarList.Add(new KeyValuePair<string, string>("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()
{
Expand Down Expand Up @@ -457,10 +481,12 @@ private void SetupMockDataCollector(Action<XmlElement, DataCollectionEvents, Dat
internal class TestableDataCollectionManager : DataCollectionManager
{
DataCollector dataCollector;
DataCollector ccDataCollector;

public TestableDataCollectionManager(IDataCollectionAttachmentManager datacollectionAttachmentManager, IMessageSink messageSink, DataCollector dataCollector) : this(datacollectionAttachmentManager, messageSink)
public TestableDataCollectionManager(IDataCollectionAttachmentManager datacollectionAttachmentManager, IMessageSink messageSink, DataCollector dataCollector, DataCollector ccDataCollector) : this(datacollectionAttachmentManager, messageSink)
{
this.dataCollector = dataCollector;
this.ccDataCollector = ccDataCollector;
}

internal TestableDataCollectionManager(IDataCollectionAttachmentManager datacollectionAttachmentManager, IMessageSink messageSink) : base(datacollectionAttachmentManager, messageSink)
Expand All @@ -474,6 +500,11 @@ protected override bool TryGetUriFromFriendlyName(string friendlyName, out strin
dataCollectorUri = "my://custom/datacollector";
return true;
}
else if (friendlyName.Equals("Code Coverage"))
{
dataCollectorUri = "my://custom/ccdatacollector";
return true;
}
else
{
dataCollectorUri = string.Empty;
Expand All @@ -483,7 +514,7 @@ protected override bool TryGetUriFromFriendlyName(string friendlyName, out strin

protected override bool IsUriValid(string uri)
{
if (uri.Equals("my://custom/datacollector"))
if (uri.Equals("my://custom/datacollector") || uri.Equals("my://custom/ccdatacollector"))
{
return true;
}
Expand All @@ -499,6 +530,12 @@ protected override DataCollector TryGetTestExtension(string extensionUri)
{
return dataCollector;
}

if (extensionUri.Equals("my://custom/ccdatacollector"))
{
return ccDataCollector;
}

return null;
}
}
Expand All @@ -508,4 +545,10 @@ protected override DataCollector TryGetTestExtension(string extensionUri)
public abstract class DataCollector2 : DataCollector
{
}

[DataCollectorFriendlyName("Code Coverage")]
[DataCollectorTypeUri("my://custom/ccdatacollector")]
public abstract class CodeCoverageDataCollector : DataCollector
{
}
}